diff --git a/.storybook/preview.ts b/.storybook/preview.ts index 95eb576..4a601d3 100644 --- a/.storybook/preview.ts +++ b/.storybook/preview.ts @@ -1,5 +1,6 @@ import type { Preview } from "@storybook/web-components"; -import "../components/theme/hot.css"; +import "../dist/ui.js"; +import "../dist/style.css"; const preview: Preview = { parameters: { diff --git a/components/button/Button.ts b/components/button/Button.ts deleted file mode 100644 index 6ef8fcd..0000000 --- a/components/button/Button.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { LitElement, css, html, unsafeCSS } from "lit"; -import { property } from "lit/decorators.js"; -import reset from "../tailwind-reset"; -import { cva } from "class-variance-authority"; -import type { HotElementProps } from "../hot-element"; - -const buttonStyle = cva( - "bg-primary text-white py-3 px-6 rounded leading-[1.15]", - { - variants: { - intent: { - primary: "bg-primary border-2 border-primary text-white", - secondary: ` - bg-white border-2 border-primary text-primary! hover:bg-lightGray - focus:bg-transparent focus:border-primary - `, - }, - disabled: { - true: "opacity-50 cursor-not-allowed", - false: "", - }, - }, - }, -); - -export class Button extends LitElement implements HotElementProps { - @property() name = "hot-button"; - - /** Disable the button, greyed out, not clickable. */ - @property({ type: Boolean }) disabled: boolean = false; - - /** CVA button type. */ - @property({ type: String }) intent: "primary" | "secondary" = "primary"; - - static styles = [ - css` - @unocss-placeholder; - `, - unsafeCSS(reset), - ]; - - protected render() { - return html``; - } - - private _handleClick(e: MouseEvent) { - // As the original event is also named 'click' - // stop propagation of the original event - e.stopPropagation(); - this.dispatchEvent(new Event("click")); - } -} - -export default Button; diff --git a/components/index.ts b/components/index.ts index b889e49..8bd7fd3 100644 --- a/components/index.ts +++ b/components/index.ts @@ -1,8 +1,24 @@ import "./theme/hot.css"; -import { Button as ButtonImport } from "./button/Button"; -export { Button } from "./button/Button"; +import '@shoelace-style/shoelace/dist/themes/light.css'; +import '@shoelace-style/shoelace/dist/themes/dark.css'; + +import '@shoelace-style/shoelace/dist/components/button/button.js'; +import '@shoelace-style/shoelace/dist/components/button-group/button-group.js'; +import '@shoelace-style/shoelace/dist/components/icon/icon.js'; +import '@shoelace-style/shoelace/dist/components/tooltip/tooltip.js'; + +import { setBasePath } from '@shoelace-style/shoelace/dist/utilities/base-path.js'; + +import { Toolbar as ToolbarImport } from "./toolbar/Toolbar"; + +// Set the base path to the folder you copied Shoelace's assets to +setBasePath('/shoelace'); + +// import { Radio as RadioImport } from "./radio/Radio"; + // export { Card } from "@/card/Card.js"; // export { Dropdown } from "@/dropdown/Dropdown.js"; // export { Toggle } from "@/toggle/Toggle.js"; -customElements.define("hot-button", ButtonImport); +customElements.define("hot-toolbar", ToolbarImport); +// customElements.define("hot-radio", RadioImport); diff --git a/components/button/Button.stories.ts b/components/toolbar/Toolbar.stories.ts similarity index 50% rename from components/button/Button.stories.ts rename to components/toolbar/Toolbar.stories.ts index 6036ebd..59fa954 100644 --- a/components/button/Button.stories.ts +++ b/components/toolbar/Toolbar.stories.ts @@ -1,20 +1,19 @@ import type { Meta, StoryObj } from "@storybook/web-components"; -import "./Button"; +import "./Toolbar"; import { html } from "lit"; const meta: Meta = { - component: "hot-button", + component: "hot-toolbar", }; export default meta; export const Template: StoryObj = { args: { - intent: "primary", - disabled: false, + tooltipPosition: "top", }, argTypes: { - intent: { - options: ["primary", "secondary"], + tooltipPosition: { + options: ["top", "bottom", "left", "right"], control: { type: "select", }, @@ -22,13 +21,10 @@ export const Template: StoryObj = { }, render: (args) => { return html` - {alert("Button Clicked")}} - > - Button - + {alert("Redo Clicked")}} + > `; }, }; diff --git a/components/toolbar/Toolbar.ts b/components/toolbar/Toolbar.ts new file mode 100644 index 0000000..f96ccbb --- /dev/null +++ b/components/toolbar/Toolbar.ts @@ -0,0 +1,114 @@ +import { LitElement, css, html, unsafeCSS } from "lit"; +import { property } from "lit/decorators.js"; +import reset from "../tailwind-reset"; +import { cva } from "class-variance-authority"; + +const toolbarStyle = cva( + "some-css-var", + { + variants: { + someProperty: { + true: "some-css-var", + false: "some-css-var", + }, + }, + }, +); + +export class Toolbar extends LitElement { + @property() name = "hot-toolbar"; + + /** Change the position of the tooltips relative to buttons. */ + @property({ type: String, attribute: "tooltip-position" }) tooltipPosition = "top"; + + static styles = [ + css` + @unocss-placeholder; + `, + unsafeCSS(reset), + ]; + + // class=${toolbarStyle({ + // someProperty: this.someProperty, + // })} + protected render() { + return html` +
+ ${this.renderButtonGroup('History', [ + { content: 'Undo', icon: 'arrow-counterclockwise', label: 'Undo', action: this.undo }, + { content: 'Redo', icon: 'arrow-clockwise', label: 'Redo', action: this.redo } + ])} + ${this.renderButtonGroup('Formatting', [ + { content: 'Bold', icon: 'type-bold', label: 'Bold', action: this.bold }, + { content: 'Italic', icon: 'type-italic', label: 'Italic', action: this.italic }, + { content: 'Underline', icon: 'type-underline', label: 'Underline', action: this.underline } + ])} + ${this.renderButtonGroup('Alignment', [ + { content: 'Align Left', icon: 'justify-left', label: 'Align Left', action: this.alignLeft }, + { content: 'Align Center', icon: 'justify', label: 'Align Center', action: this.alignCenter }, + { content: 'Align Right', icon: 'justify-right', label: 'Align Right', action: this.alignRight } + ])} +
+ `; + } + + private renderButtonGroup(label: string, buttons: Array<{ content: string, icon: string, label: string, action?: (e: MouseEvent) => void }>) { + return html` + + ${buttons.map(button => this.renderButton(button))} + + `; + } + + private renderButton({ content, icon, label, action }: { content: string, icon: string, label: string, action?: (e: MouseEvent) => void }) { + return html` + + {})}> + + `; + } + + private readonly undo = (e: MouseEvent) => { + // As the original event is also named 'click' + // stop propagation of the original event + e.stopPropagation(); + this.dispatchEvent(new Event("hot-undo-click")); + } + + private readonly redo = (e: MouseEvent) => { + e.stopPropagation(); + this.dispatchEvent(new Event("hot-redo-click")); + } + + private readonly bold = (e: MouseEvent) => { + e.stopPropagation(); + this.dispatchEvent(new Event("hot-bold-click")); + } + + private readonly italic = (e: MouseEvent) => { + e.stopPropagation(); + this.dispatchEvent(new Event("hot-italic-click")); + } + + private readonly underline = (e: MouseEvent) => { + e.stopPropagation(); + this.dispatchEvent(new Event("hot-underline-click")); + } + + private readonly alignLeft = (e: MouseEvent) => { + e.stopPropagation(); + this.dispatchEvent(new Event("hot-leftalign-click")); + } + + private readonly alignCenter = (e: MouseEvent) => { + e.stopPropagation(); + this.dispatchEvent(new Event("hot-centeralign-click")); + } + + private readonly alignRight = (e: MouseEvent) => { + e.stopPropagation(); + this.dispatchEvent(new Event("hot-rightalign-click")); + } +} + +export default Toolbar; diff --git a/components/utils/cva.ts b/components/utils/cva.ts index 8c2841f..7fb337c 100644 --- a/components/utils/cva.ts +++ b/components/utils/cva.ts @@ -1,17 +1,9 @@ import { cva } from "class-variance-authority"; import { type ClassValue } from "clsx"; -import { Simplify } from "type-fest"; import { type ClassProp, type StringToBoolean, } from "class-variance-authority/dist/types"; -import { type LitElement } from "lit"; - -function decorateCva(cvaStyle: ReturnType["variants"]) { - return function (target: LitElement, propertyKey: string) { - console.log("decorateCva", target, propertyKey); - }; -} export function generateCvaProperties(cvaReturn: ReturnType) { const cvaProperties: Record< diff --git a/docs/components/hot-button.md b/docs/components/hot-button.md deleted file mode 100644 index df3a66e..0000000 --- a/docs/components/hot-button.md +++ /dev/null @@ -1,14 +0,0 @@ -# hot-button - -## Properties - -| Property | Attribute | Type | Default | Description | -| ---------- | ---------- | -------------------------- | --------- | ---------------------------------------------- | -| `disabled` | `disabled` | `boolean` | false | Disable the button, greyed out, not clickable. | -| `intent` | `intent` | `"primary" \| "secondary"` | "primary" | | - -## Events - -| Event | -| ------- | -| `click` | diff --git a/docs/components/hot-toolbar.md b/docs/components/hot-toolbar.md new file mode 100644 index 0000000..37a70ec --- /dev/null +++ b/docs/components/hot-toolbar.md @@ -0,0 +1,21 @@ +# hot-toolbar + +## Properties + +| Property | Attribute | Type | Default | Description | +|-------------------|--------------------|----------|---------------|--------------------------------------------------| +| `name` | `name` | `string` | "hot-toolbar" | | +| `tooltipPosition` | `tooltip-position` | `string` | "top" | Change the position of the tooltips relative to buttons. | + +## Events + +| Event | +|-------------------------| +| `hot-bold-click` | +| `hot-centeralign-click` | +| `hot-italic-click` | +| `hot-leftalign-click` | +| `hot-redo-click` | +| `hot-rightalign-click` | +| `hot-underline-click` | +| `hot-undo-click` | diff --git a/examples/react/index.html b/examples/react/index.html index 3eabd89..6d9a7a1 100644 --- a/examples/react/index.html +++ b/examples/react/index.html @@ -5,11 +5,11 @@ HOTOSM UI React Example diff --git a/examples/react/package.json b/examples/react/package.json index 71db8b1..680967c 100644 --- a/examples/react/package.json +++ b/examples/react/package.json @@ -4,11 +4,11 @@ "version": "0.0.0", "type": "module", "scripts": { + "serve-web-components": "pnpm --prefix ../../ run serve", "dev:build-web-components": "pnpm --prefix ../../ run build", - "dev:serve-web-components": "pnpm --prefix ../../ run serve", "dev:start-server": "vite", "dev": "pnpm run '/^dev:.*/'", - "build": "run-p type-check \"build-only {@}\" --", + "build": "vite build", "preview": "vite preview", "build-only": "vite build" }, @@ -32,7 +32,8 @@ "@types/react-dom": "^18.2.23", "@vitejs/plugin-react": "^4.2.1", "typescript": "~5.4.0", - "vite": "^5.1.6" + "vite": "^5.1.6", + "vite-plugin-static-copy": "^1.0.2" }, "dependencies": { "react": "^18.2.0", diff --git a/examples/react/pnpm-lock.yaml b/examples/react/pnpm-lock.yaml index 1285bc6..c426529 100644 --- a/examples/react/pnpm-lock.yaml +++ b/examples/react/pnpm-lock.yaml @@ -40,6 +40,9 @@ devDependencies: vite: specifier: ^5.1.6 version: 5.2.7(@types/node@20.12.2) + vite-plugin-static-copy: + specifier: ^1.0.2 + version: 1.0.2(vite@5.2.7) packages: @@ -513,6 +516,27 @@ packages: '@types/react': 18.2.73 dev: false + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.17.1 + dev: true + /@rollup/rollup-android-arm-eabi@4.13.2: resolution: {integrity: sha512-3XFIDKWMFZrMnao1mJhnOT1h2g0169Os848NhhmGweEcfJ4rCi+3yMCOLG4zA61rbJdkcrM/DjVZm9Hg5p5w7g==} cpu: [arm] @@ -718,6 +742,26 @@ packages: color-convert: 1.9.3 dev: true + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + /browserslist@4.23.0: resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -742,6 +786,21 @@ packages: supports-color: 5.5.0 dev: true + /chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + /color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} dependencies: @@ -816,6 +875,39 @@ packages: engines: {node: '>=0.8.0'} dev: true + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fastq@1.17.1: + resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + dependencies: + reusify: 1.0.4 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + /fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -829,16 +921,51 @@ packages: engines: {node: '>=6.9.0'} dev: true + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + /globals@11.12.0: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} dev: true + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} dev: true + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.3.0 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + /js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} @@ -854,6 +981,14 @@ packages: hasBin: true dev: true + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + /loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -867,6 +1002,19 @@ packages: yallist: 3.1.1 dev: true + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true @@ -881,10 +1029,20 @@ packages: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} dev: true + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + /picocolors@1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} dev: true + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + /postcss@8.4.38: resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} engines: {node: ^10 || ^12 || >=14} @@ -894,6 +1052,10 @@ packages: source-map-js: 1.2.0 dev: true + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + /react-dom@18.2.0(react@18.2.0): resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} peerDependencies: @@ -916,6 +1078,18 @@ packages: loose-envify: 1.4.0 dev: false + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + /rollup@4.13.2: resolution: {integrity: sha512-MIlLgsdMprDBXC+4hsPgzWUasLO9CE4zOkj/u6j+Z6j5A4zRY+CtiXAdJyPtgCsc42g658Aeh1DlrdVEJhsL2g==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -941,6 +1115,12 @@ packages: fsevents: 2.3.3 dev: true + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + /scheduler@0.23.0: resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} dependencies: @@ -969,6 +1149,13 @@ packages: engines: {node: '>=4'} dev: true + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + /typescript@5.4.3: resolution: {integrity: sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==} engines: {node: '>=14.17'} @@ -979,6 +1166,11 @@ packages: resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} dev: true + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + /update-browserslist-db@1.0.13(browserslist@4.23.0): resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} hasBin: true @@ -990,6 +1182,19 @@ packages: picocolors: 1.0.0 dev: true + /vite-plugin-static-copy@1.0.2(vite@5.2.7): + resolution: {integrity: sha512-AfmEF+a/mfjsUsrgjbCkhzUCeIUF4EKQXXt3Ie1cour9MBpy6f6GphbdW2td28oYfOrwCyRzFCksgLkpk58q6Q==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 + dependencies: + chokidar: 3.6.0 + fast-glob: 3.3.2 + fs-extra: 11.2.0 + picocolors: 1.0.0 + vite: 5.2.7(@types/node@20.12.2) + dev: true + /vite@5.2.7(@types/node@20.12.2): resolution: {integrity: sha512-k14PWOKLI6pMaSzAuGtT+Cf0YmIx12z9YGon39onaJNy8DLBfBJrzg9FQEmkAM5lpHBZs9wksWAsyF/HkpEwJA==} engines: {node: ^18.0.0 || >=20.0.0} diff --git a/examples/react/src/App.tsx b/examples/react/src/App.tsx index 7473d71..1ad40b3 100644 --- a/examples/react/src/App.tsx +++ b/examples/react/src/App.tsx @@ -1,14 +1,46 @@ import hotLogo from './assets/hot_logo.png'; import { useState } from 'react'; - -import HotButton from '../../../react/HotButton'; - +import Toolbar from '../../../react/HotToolbar'; const App = () => { - const [counter, setCounter] = useState(0); + const [undoCount, setUndoCount] = useState(0); + const [redoCount, setRedoCount] = useState(0); + const [boldCount, setBoldCount] = useState(0); + const [italicCount, setItalicCount] = useState(0); + const [underlineCount, setUnderlineCount] = useState(0); + const [leftAlignCount, setLeftAlignCount] = useState(0); + const [centerAlignCount, setCenterAlignCount] = useState(0); + const [rightAlignCount, setRightAlignCount] = useState(0); - const clickButton = () => { - setCounter((prevCounter) => prevCounter + 1); + const incrementCounter = (type) => { + switch (type) { + case 'undo': + setUndoCount((prevCount) => prevCount + 1); + break; + case 'redo': + setRedoCount((prevCount) => prevCount + 1); + break; + case 'bold': + setBoldCount((prevCount) => prevCount + 1); + break; + case 'italic': + setItalicCount((prevCount) => prevCount + 1); + break; + case 'underline': + setUnderlineCount((prevCount) => prevCount + 1); + break; + case 'leftAlign': + setLeftAlignCount((prevCount) => prevCount + 1); + break; + case 'centerAlign': + setCenterAlignCount((prevCount) => prevCount + 1); + break; + case 'rightAlign': + setRightAlignCount((prevCount) => prevCount + 1); + break; + default: + break; + } }; return ( @@ -21,12 +53,26 @@ const App = () => {

HOTOSM UI React Example

- Click Me + { incrementCounter('undo'); }} + onHotRedoClick={() => { incrementCounter('redo'); }} + onHotBoldClick={() => { incrementCounter('bold'); }} + onHotItalicClick={() => { incrementCounter('italic'); }} + onHotUnderlineClick={() => { incrementCounter('underline'); }} + onHotLeftalignClick={() => { incrementCounter('leftAlign'); }} + onHotCenteralignClick={() => { incrementCounter('centerAlign'); }} + onHotRightalignClick={() => { incrementCounter('rightAlign'); }} + /> -

Counter: {counter}

+

Undo: {undoCount}

+

Redo: {redoCount}

+

Bold: {boldCount}

+

Italic: {italicCount}

+

Underline: {underlineCount}

+

Justify Left: {leftAlignCount}

+

Justify Center: {centerAlignCount}

+

Justify Right: {rightAlignCount}

); }; diff --git a/examples/react/vite.config.ts b/examples/react/vite.config.ts index 3da279a..5696548 100644 --- a/examples/react/vite.config.ts +++ b/examples/react/vite.config.ts @@ -2,11 +2,20 @@ import { fileURLToPath, URL } from 'node:url' import { defineConfig } from 'vite' import react from '@vitejs/plugin-react' +import { viteStaticCopy } from 'vite-plugin-static-copy'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [ - react({}) + react({}), + viteStaticCopy({ + targets: [ + { + src: '../../dist/*', + dest: '.' + } + ] + }), ], resolve: { alias: { diff --git a/examples/svelte/index.html b/examples/svelte/index.html index 96bfa42..88a5e84 100644 --- a/examples/svelte/index.html +++ b/examples/svelte/index.html @@ -5,11 +5,11 @@ HOTOSM UI Svelte Example diff --git a/examples/svelte/package.json b/examples/svelte/package.json index 5cc2355..87647ca 100644 --- a/examples/svelte/package.json +++ b/examples/svelte/package.json @@ -4,8 +4,8 @@ "version": "0.0.0", "type": "module", "scripts": { + "serve-web-components": "pnpm --prefix ../../ run serve", "dev:build-web-components": "pnpm --prefix ../../ run build", - "dev:serve-web-components": "pnpm --prefix ../../ run serve", "dev:start-server": "vite", "dev": "pnpm run '/^dev:.*/'", "build": "vite build", @@ -19,6 +19,7 @@ "svelte-check": "^3.6.4", "tslib": "^2.6.2", "typescript": "^5.2.2", - "vite": "^5.1.4" + "vite": "^5.1.4", + "vite-plugin-static-copy": "^1.0.2" } } diff --git a/examples/svelte/pnpm-lock.yaml b/examples/svelte/pnpm-lock.yaml index f5dc014..eb5fab0 100644 --- a/examples/svelte/pnpm-lock.yaml +++ b/examples/svelte/pnpm-lock.yaml @@ -26,6 +26,9 @@ devDependencies: vite: specifier: ^5.1.4 version: 5.1.4 + vite-plugin-static-copy: + specifier: ^1.0.2 + version: 1.0.2(vite@5.1.4) packages: @@ -634,6 +637,15 @@ packages: to-regex-range: 5.0.1 dev: true + /fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + /fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} dev: true @@ -717,6 +729,14 @@ packages: '@types/estree': 1.0.5 dev: true + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + /kleur@4.1.5: resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} engines: {node: '>=6'} @@ -1051,6 +1071,24 @@ packages: hasBin: true dev: true + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + + /vite-plugin-static-copy@1.0.2(vite@5.1.4): + resolution: {integrity: sha512-AfmEF+a/mfjsUsrgjbCkhzUCeIUF4EKQXXt3Ie1cour9MBpy6f6GphbdW2td28oYfOrwCyRzFCksgLkpk58q6Q==} + engines: {node: ^18.0.0 || >=20.0.0} + peerDependencies: + vite: ^5.0.0 + dependencies: + chokidar: 3.6.0 + fast-glob: 3.3.2 + fs-extra: 11.2.0 + picocolors: 1.0.0 + vite: 5.1.4 + dev: true + /vite@5.1.4: resolution: {integrity: sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==} engines: {node: ^18.0.0 || >=20.0.0} diff --git a/examples/svelte/src/App.svelte b/examples/svelte/src/App.svelte index 756f6f3..61f24de 100644 --- a/examples/svelte/src/App.svelte +++ b/examples/svelte/src/App.svelte @@ -2,15 +2,57 @@ import hotLogo from './assets/hot_logo.png'; import { onMount } from 'svelte'; - let counter = 0; + let undoCount = 0; + let redoCount = 0; + let boldCount = 0; + let italicCount = 0; + let underlineCount = 0; + let leftAlignCount = 0; + let centerAlignCount = 0; + let rightAlignCount = 0; - const clickButton = () => { - counter++; + const undoClick = () => { + undoCount++; }; - // Optional: You can reset the counter when the component mounts + const redoClick = () => { + redoCount++; + }; + + const boldClick = () => { + boldCount++; + }; + + const italicClick = () => { + italicCount++; + }; + + const underlineClick = () => { + underlineCount++; + }; + + const leftAlignClick = () => { + leftAlignCount++; + }; + + const centerAlignClick = () => { + centerAlignCount++; + }; + + const rightAlignClick = () => { + rightAlignCount++; + }; + + // Reset values when component mounts onMount(() => { - counter = 0; + undoCount = 0; + redoCount = 0; + boldCount = 0; + italicCount = 0; + underlineCount = 0; + leftAlignCount = 0; + centerAlignCount = 0; + rightAlignCount = 0; }); @@ -23,9 +65,27 @@

HOTOSM UI Svelte Example

- Click Me + + +

Undo: {undoCount}

+

Redo: {redoCount}

+

Bold: {boldCount}

+

Italic: {italicCount}

+

Underline: {underlineCount}

+

Justify Left: {leftAlignCount}

+

Justify Center: {centerAlignCount}

+

Justify Right: {rightAlignCount}

-

Counter: {counter}