luxen-ui 0.6.2 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli.mjs +54 -10
- package/cdn/chunks/decorate.js +1 -1
- package/cdn/chunks/floating-ui.dom.js +2 -0
- package/cdn/chunks/floating-ui.dom.js.map +1 -0
- package/cdn/chunks/lit-html.js +3 -0
- package/cdn/chunks/lit-html.js.map +1 -0
- package/cdn/chunks/lit.js +1 -2
- package/cdn/chunks/lit.js.map +1 -1
- package/cdn/chunks/module.js +717 -0
- package/cdn/chunks/module.js.map +1 -0
- package/cdn/chunks/native.js +2 -0
- package/cdn/chunks/native.js.map +1 -0
- package/cdn/chunks/static-html.js +2 -0
- package/cdn/chunks/static-html.js.map +1 -0
- package/cdn/custom-elements.json +1412 -12629
- package/cdn/elements/avatar/avatar.d.ts +5 -0
- package/cdn/elements/avatar/avatar.d.ts.map +1 -1
- package/cdn/elements/avatar/avatar.js +5 -5
- package/cdn/elements/avatar/avatar.js.map +1 -1
- package/cdn/elements/button/button.meta.d.ts +33 -0
- package/cdn/elements/button/button.meta.d.ts.map +1 -0
- package/cdn/elements/button/button.meta.js +0 -0
- package/cdn/elements/carousel/carousel.d.ts +6 -0
- package/cdn/elements/carousel/carousel.d.ts.map +1 -1
- package/cdn/elements/carousel/carousel.js +1 -1
- package/cdn/elements/carousel/carousel.js.map +1 -1
- package/cdn/elements/carousel-item/carousel-item.d.ts +2 -0
- package/cdn/elements/carousel-item/carousel-item.d.ts.map +1 -1
- package/cdn/elements/carousel-item/carousel-item.js +1 -1
- package/cdn/elements/carousel-item/carousel-item.js.map +1 -1
- package/cdn/elements/close-button/close-button.meta.d.ts +24 -0
- package/cdn/elements/close-button/close-button.meta.d.ts.map +1 -0
- package/cdn/elements/close-button/close-button.meta.js +0 -0
- package/cdn/elements/dialog/dialog.d.ts +12 -6
- package/cdn/elements/dialog/dialog.d.ts.map +1 -1
- package/cdn/elements/dialog/dialog.js +8 -5
- package/cdn/elements/dialog/dialog.js.map +1 -1
- package/cdn/elements/dialog/dialog.styles.js +1 -1
- package/cdn/elements/dialog/dialog.styles.js.map +1 -1
- package/cdn/elements/disclosure/disclosure.meta.d.ts +28 -0
- package/cdn/elements/disclosure/disclosure.meta.d.ts.map +1 -0
- package/cdn/elements/disclosure/disclosure.meta.js +0 -0
- package/cdn/elements/divider/divider.d.ts +1 -1
- package/cdn/elements/divider/divider.js.map +1 -1
- package/cdn/elements/drawer/drawer.d.ts +5 -0
- package/cdn/elements/drawer/drawer.d.ts.map +1 -1
- package/cdn/elements/drawer/drawer.js +1 -1
- package/cdn/elements/drawer/drawer.js.map +1 -1
- package/cdn/elements/dropdown/dropdown.d.ts +2 -0
- package/cdn/elements/dropdown/dropdown.d.ts.map +1 -1
- package/cdn/elements/dropdown/dropdown.js +1 -1
- package/cdn/elements/dropdown/dropdown.js.map +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.d.ts +2 -0
- package/cdn/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.js +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.js.map +1 -1
- package/cdn/elements/icon/icon.js +1 -1
- package/cdn/elements/icon/icon.js.map +1 -1
- package/cdn/elements/input-otp/input-otp.d.ts +2 -0
- package/cdn/elements/input-otp/input-otp.d.ts.map +1 -1
- package/cdn/elements/input-otp/input-otp.js.map +1 -1
- package/cdn/elements/input-stepper/input-stepper.d.ts +2 -0
- package/cdn/elements/input-stepper/input-stepper.d.ts.map +1 -1
- package/cdn/elements/input-stepper/input-stepper.js +1 -1
- package/cdn/elements/input-stepper/input-stepper.js.map +1 -1
- package/cdn/elements/kbd/kbd.meta.d.ts +14 -0
- package/cdn/elements/kbd/kbd.meta.d.ts.map +1 -0
- package/cdn/elements/kbd/kbd.meta.js +0 -0
- package/cdn/elements/popover/popover.js +1 -1
- package/cdn/elements/popover/popover.js.map +1 -1
- package/cdn/elements/progress/progress.meta.d.ts +22 -0
- package/cdn/elements/progress/progress.meta.d.ts.map +1 -0
- package/cdn/elements/progress/progress.meta.js +0 -0
- package/cdn/elements/prose-editor/index.d.ts +2 -0
- package/cdn/elements/prose-editor/index.d.ts.map +1 -0
- package/cdn/elements/prose-editor/index.js +2 -0
- package/cdn/elements/prose-editor/index.js.map +1 -0
- package/cdn/elements/prose-editor/prose-editor.d.ts +113 -0
- package/cdn/elements/prose-editor/prose-editor.d.ts.map +1 -0
- package/cdn/elements/prose-editor/prose-editor.js +180 -0
- package/cdn/elements/prose-editor/prose-editor.js.map +1 -0
- package/cdn/elements/rating/rating.d.ts +2 -0
- package/cdn/elements/rating/rating.d.ts.map +1 -1
- package/cdn/elements/rating/rating.js +1 -1
- package/cdn/elements/rating/rating.js.map +1 -1
- package/cdn/elements/select/select.meta.d.ts +28 -0
- package/cdn/elements/select/select.meta.d.ts.map +1 -0
- package/cdn/elements/select/select.meta.js +0 -0
- package/cdn/elements/skeleton/skeleton.d.ts +3 -0
- package/cdn/elements/skeleton/skeleton.d.ts.map +1 -1
- package/cdn/elements/skeleton/skeleton.js.map +1 -1
- package/cdn/elements/spinner/spinner.js +1 -1
- package/cdn/elements/spinner/spinner.js.map +1 -1
- package/cdn/elements/sticky-bar/sticky-bar.js +1 -1
- package/cdn/elements/sticky-bar/sticky-bar.js.map +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.d.ts +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.d.ts.map +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.js +26 -26
- package/cdn/elements/stories-viewer/stories-viewer.js.map +1 -1
- package/cdn/elements/story/story.d.ts +10 -1
- package/cdn/elements/story/story.d.ts.map +1 -1
- package/cdn/elements/story/story.js +20 -20
- package/cdn/elements/story/story.js.map +1 -1
- package/cdn/elements/toast/toast.d.ts +5 -0
- package/cdn/elements/toast/toast.d.ts.map +1 -1
- package/cdn/elements/toast/toast.js.map +1 -1
- package/cdn/elements/tooltip/tooltip.js +1 -1
- package/cdn/elements/tooltip/tooltip.js.map +1 -1
- package/cdn/elements/tree/tree.d.ts +2 -0
- package/cdn/elements/tree/tree.d.ts.map +1 -1
- package/cdn/elements/tree/tree.js +1 -1
- package/cdn/elements/tree/tree.js.map +1 -1
- package/cdn/elements/tree-item/tree-item.d.ts +2 -0
- package/cdn/elements/tree-item/tree-item.d.ts.map +1 -1
- package/cdn/elements/tree-item/tree-item.js +1 -1
- package/cdn/elements/tree-item/tree-item.js.map +1 -1
- package/cdn/registry.d.ts +1 -1
- package/cdn/registry.d.ts.map +1 -1
- package/cdn/registry.js.map +1 -1
- package/cdn/shared/controllers/has-slot-controller.d.ts +37 -0
- package/cdn/shared/controllers/has-slot-controller.d.ts.map +1 -0
- package/cdn/shared/controllers/has-slot-controller.js +2 -0
- package/cdn/shared/controllers/has-slot-controller.js.map +1 -0
- package/cdn/shared/controllers/popover.js +1 -1
- package/cdn/shared/controllers/popover.js.map +1 -1
- package/cdn/shared/styles/host.styles.js +1 -1
- package/cdn/standalone.css +132 -1
- package/cdn/standalone.js +25743 -191
- package/cdn/standalone.js.map +1 -1
- package/cdn/static-tag.d.ts +17 -0
- package/cdn/static-tag.d.ts.map +1 -0
- package/cdn/static-tag.js +2 -0
- package/cdn/static-tag.js.map +1 -0
- package/cdn/styles/elements/prose-editor.css +129 -0
- package/cdn/styles/elements/toast.css +1 -1
- package/dist/css/elements/prose-editor.css +129 -0
- package/dist/css/elements/toast.css +1 -1
- package/dist/custom-elements.json +1412 -12629
- package/dist/elements/avatar/avatar.d.ts +5 -0
- package/dist/elements/avatar/avatar.d.ts.map +1 -1
- package/dist/elements/avatar/avatar.js +5 -0
- package/dist/elements/button/button.meta.d.ts +33 -0
- package/dist/elements/button/button.meta.d.ts.map +1 -0
- package/dist/elements/button/button.meta.js +44 -0
- package/dist/elements/carousel/carousel.d.ts +6 -0
- package/dist/elements/carousel/carousel.d.ts.map +1 -1
- package/dist/elements/carousel/carousel.js +6 -0
- package/dist/elements/carousel-item/carousel-item.d.ts +2 -0
- package/dist/elements/carousel-item/carousel-item.d.ts.map +1 -1
- package/dist/elements/carousel-item/carousel-item.js +2 -0
- package/dist/elements/close-button/close-button.meta.d.ts +24 -0
- package/dist/elements/close-button/close-button.meta.d.ts.map +1 -0
- package/dist/elements/close-button/close-button.meta.js +30 -0
- package/dist/elements/dialog/dialog.css +15 -0
- package/dist/elements/dialog/dialog.d.ts +12 -6
- package/dist/elements/dialog/dialog.d.ts.map +1 -1
- package/dist/elements/dialog/dialog.js +21 -7
- package/dist/elements/disclosure/disclosure.meta.d.ts +28 -0
- package/dist/elements/disclosure/disclosure.meta.d.ts.map +1 -0
- package/dist/elements/disclosure/disclosure.meta.js +34 -0
- package/dist/elements/divider/divider.d.ts +1 -1
- package/dist/elements/divider/divider.js +1 -1
- package/dist/elements/drawer/drawer.d.ts +5 -0
- package/dist/elements/drawer/drawer.d.ts.map +1 -1
- package/dist/elements/drawer/drawer.js +5 -0
- package/dist/elements/dropdown/dropdown.d.ts +2 -0
- package/dist/elements/dropdown/dropdown.d.ts.map +1 -1
- package/dist/elements/dropdown/dropdown.js +2 -0
- package/dist/elements/dropdown-item/dropdown-item.d.ts +2 -0
- package/dist/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
- package/dist/elements/dropdown-item/dropdown-item.js +2 -0
- package/dist/elements/input-otp/input-otp.d.ts +2 -0
- package/dist/elements/input-otp/input-otp.d.ts.map +1 -1
- package/dist/elements/input-otp/input-otp.js +2 -0
- package/dist/elements/input-stepper/input-stepper.d.ts +2 -0
- package/dist/elements/input-stepper/input-stepper.d.ts.map +1 -1
- package/dist/elements/input-stepper/input-stepper.js +5 -1
- package/dist/elements/kbd/kbd.meta.d.ts +14 -0
- package/dist/elements/kbd/kbd.meta.d.ts.map +1 -0
- package/dist/elements/kbd/kbd.meta.js +20 -0
- package/dist/elements/progress/progress.meta.d.ts +22 -0
- package/dist/elements/progress/progress.meta.d.ts.map +1 -0
- package/dist/elements/progress/progress.meta.js +28 -0
- package/dist/elements/prose-editor/index.d.ts +2 -0
- package/dist/elements/prose-editor/index.d.ts.map +1 -0
- package/dist/elements/prose-editor/index.js +4 -0
- package/dist/elements/prose-editor/prose-editor.css +133 -0
- package/dist/elements/prose-editor/prose-editor.d.ts +114 -0
- package/dist/elements/prose-editor/prose-editor.d.ts.map +1 -0
- package/dist/elements/prose-editor/prose-editor.js +481 -0
- package/dist/elements/rating/rating.d.ts +2 -0
- package/dist/elements/rating/rating.d.ts.map +1 -1
- package/dist/elements/rating/rating.js +2 -0
- package/dist/elements/select/select.meta.d.ts +28 -0
- package/dist/elements/select/select.meta.d.ts.map +1 -0
- package/dist/elements/select/select.meta.js +34 -0
- package/dist/elements/skeleton/skeleton.d.ts +3 -0
- package/dist/elements/skeleton/skeleton.d.ts.map +1 -1
- package/dist/elements/skeleton/skeleton.js +3 -0
- package/dist/elements/stories-viewer/stories-viewer.d.ts +1 -1
- package/dist/elements/stories-viewer/stories-viewer.d.ts.map +1 -1
- package/dist/elements/stories-viewer/stories-viewer.js +23 -19
- package/dist/elements/story/story.d.ts +10 -1
- package/dist/elements/story/story.d.ts.map +1 -1
- package/dist/elements/story/story.js +29 -17
- package/dist/elements/toast/toast.d.ts +5 -0
- package/dist/elements/toast/toast.d.ts.map +1 -1
- package/dist/elements/toast/toast.js +5 -0
- package/dist/elements/tree/tree.d.ts +2 -0
- package/dist/elements/tree/tree.d.ts.map +1 -1
- package/dist/elements/tree/tree.js +2 -0
- package/dist/elements/tree-item/tree-item.d.ts +2 -0
- package/dist/elements/tree-item/tree-item.d.ts.map +1 -1
- package/dist/elements/tree-item/tree-item.js +2 -0
- package/dist/metadata/avatar.json +83 -0
- package/dist/metadata/badge.json +59 -0
- package/dist/metadata/button.json +138 -0
- package/dist/metadata/carousel-item.json +32 -0
- package/dist/metadata/carousel.json +388 -0
- package/dist/metadata/close-button.json +90 -0
- package/dist/metadata/dialog.json +163 -0
- package/dist/metadata/disclosure.json +88 -0
- package/dist/metadata/divider.json +65 -0
- package/dist/metadata/drawer.json +176 -0
- package/dist/metadata/dropdown-item.json +85 -0
- package/dist/metadata/dropdown.json +157 -0
- package/dist/metadata/icon.json +49 -0
- package/dist/metadata/index.json +4062 -0
- package/dist/metadata/input-otp.json +86 -0
- package/dist/metadata/input-stepper.json +122 -0
- package/dist/metadata/kbd.json +37 -0
- package/dist/metadata/popover.json +157 -0
- package/dist/metadata/progress.json +71 -0
- package/dist/metadata/prose-editor.json +365 -0
- package/dist/metadata/rating.json +126 -0
- package/dist/metadata/select.json +82 -0
- package/dist/metadata/skeleton.json +56 -0
- package/dist/metadata/spinner.json +47 -0
- package/dist/metadata/sticky-bar.json +93 -0
- package/dist/metadata/stories-viewer.json +316 -0
- package/dist/metadata/stories.json +109 -0
- package/dist/metadata/story.json +148 -0
- package/dist/metadata/tabs.json +74 -0
- package/dist/metadata/toast.json +122 -0
- package/dist/metadata/tooltip.json +144 -0
- package/dist/metadata/tree-item.json +199 -0
- package/dist/metadata/tree.json +130 -0
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/shared/controllers/has-slot-controller.d.ts +37 -0
- package/dist/shared/controllers/has-slot-controller.d.ts.map +1 -0
- package/dist/shared/controllers/has-slot-controller.js +66 -0
- package/dist/static-tag.d.ts +17 -0
- package/dist/static-tag.d.ts.map +1 -0
- package/dist/static-tag.js +22 -0
- package/dist/templates/elements/avatar.md +21 -24
- package/dist/templates/elements/badge.md +9 -15
- package/dist/templates/elements/button.md +31 -41
- package/dist/templates/elements/close-button.md +24 -36
- package/dist/templates/elements/dialog.md +73 -54
- package/dist/templates/elements/drawer.md +39 -52
- package/dist/templates/elements/progress.md +13 -23
- package/dist/templates/elements/prose-editor.md +211 -0
- package/dist/templates/elements/select.md +20 -31
- package/dist/templates/elements/sticky-bar.md +16 -60
- package/dist/templates/elements/toast.md +33 -53
- package/dist/templates/elements/tree.md +39 -67
- package/elements.json +46 -1
- package/package.json +13 -3
- package/templates/SKILL.md.tpl +5 -1
|
@@ -8,6 +8,8 @@ import { LuxenElement } from '../../shared/luxen-element.js';
|
|
|
8
8
|
* @summary Stripe-style OTP input with visual digit cells over a hidden native input.
|
|
9
9
|
* @customElement l-input-otp
|
|
10
10
|
*
|
|
11
|
+
* @attribute size - sm | lg — Cell size. Default is md.
|
|
12
|
+
*
|
|
11
13
|
* @cssproperty --digits - Number of digit boxes (default: 6). Must match input's maxlength.
|
|
12
14
|
* @cssproperty --cell-size - Cell width and height (default: 2.75rem). Font size scales automatically.
|
|
13
15
|
* @cssproperty --cell-gap - Space between cells (default: 0.5rem).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-otp.d.ts","sourceRoot":"","sources":["../../../src/html/elements/input-otp/input-otp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D
|
|
1
|
+
{"version":3,"file":"input-otp.d.ts","sourceRoot":"","sources":["../../../src/html/elements/input-otp/input-otp.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,QAAS,SAAQ,YAAY;IAC/B,gBAAgB;IAIzB,sFAAsF;IAEtF,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,UAAU,CAAkB;IACpC,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,YAAY,CAAgC;IACpD,OAAO,CAAC,YAAY,CAAS;IAEpB,iBAAiB;IAKjB,oBAAoB;IAO7B,OAAO,CAAC,MAAM;IA4Dd,OAAO,CAAC,SAAS;IAoBjB,OAAO,CAAC,YAAY,CAyBlB;IAEF,OAAO,CAAC,WAAW,CAIjB;IAEF,OAAO,CAAC,oBAAoB,CAE1B;CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-otp.js","names":[],"sources":["../../../src/html/elements/input-otp/input-otp.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\n\n/**\n * Enhances a child `<input>` with visual digit cells (Stripe-style OTP input).\n *\n * A single hidden `<input>` handles keyboard, paste, and autocomplete.\n * Visual cells are rendered as real DOM elements with individual borders and focus ring.\n *\n * @summary Stripe-style OTP input with visual digit cells over a hidden native input.\n * @customElement l-input-otp\n *\n * @cssproperty --digits - Number of digit boxes (default: 6). Must match input's maxlength.\n * @cssproperty --cell-size - Cell width and height (default: 2.75rem). Font size scales automatically.\n * @cssproperty --cell-gap - Space between cells (default: 0.5rem).\n * @cssproperty --cell-bg-color - Cell background color.\n * @cssproperty --cell-border-color - Cell border color.\n * @cssproperty --cell-border-radius - Cell border-radius.\n * @cssproperty --cell-focus-color - Border + ring color of the active (focused) cell.\n * @cssproperty --cell-focus-ring - `box-shadow` of the active cell ring (defaults to a 1px solid ring; set to `none` to disable).\n */\nexport class InputOtp extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n /** Position after which to insert a visual separator (e.g., 3 for a 3-3 grouping). */\n @property({ type: Number, reflect: true, attribute: 'separator-after' })\n separatorAfter?: number;\n\n private _input!: HTMLInputElement;\n private _container!: HTMLDivElement;\n private _cells: HTMLDivElement[] = [];\n private _separatorEl: HTMLSpanElement | null = null;\n private _initialized = false;\n\n override connectedCallback() {\n super.connectedCallback();\n requestAnimationFrame(() => this._setup());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n const input = this.querySelector<HTMLInputElement>('input');\n if (!input) return;\n\n this._input = input;\n\n // Derive digit count from --digits CSS custom property (default 6)\n const digits = Number(getComputedStyle(this).getPropertyValue('--digits').trim()) || 6;\n\n // Set sensible defaults — author can still override via HTML attributes\n const defaults: Record<string, string> = {\n type: 'text',\n inputmode: 'numeric',\n autocomplete: 'one-time-code',\n maxlength: String(digits),\n pattern: String.raw`\\d{${digits}}`,\n };\n for (const [attr, value] of Object.entries(defaults)) {\n if (!this._input.hasAttribute(attr)) {\n this._input.setAttribute(attr, value);\n }\n }\n\n // Build visual cells container\n this._container = document.createElement('div');\n this._container.className = 'l-input-otp-cells';\n this._container.setAttribute('aria-hidden', 'true');\n\n for (let i = 0; i < digits; i++) {\n const cell = document.createElement('div');\n cell.className = 'l-input-otp-cell';\n cell.appendChild(document.createElement('span'));\n this._cells.push(cell);\n this._container.appendChild(cell);\n\n // Insert separator after the specified position\n if (this.separatorAfter && i === this.separatorAfter - 1 && i < digits - 1) {\n this._separatorEl = document.createElement('span');\n this._separatorEl.className = 'l-input-otp-separator';\n this._container.appendChild(this._separatorEl);\n }\n }\n\n // Wrap: insert container before input, then move input inside\n this._input.replaceWith(this._container);\n this._container.appendChild(this._input);\n this._initialized = true;\n\n // Populate cells if input already has a value (e.g. disabled with prefilled value)\n this._updateCells();\n\n // Events — focus is deferred so it runs after the click that triggered it\n // (otherwise selectionStart is stale and the active cell flickers).\n this._input.addEventListener('input', this._updateCells);\n this._input.addEventListener('click', this._updateCells);\n this._input.addEventListener('keyup', this._updateCells);\n this._input.addEventListener('focus', this._scheduleUpdateCells);\n this._input.addEventListener('blur', this._clearCells);\n }\n\n private _teardown() {\n if (!this._initialized) return;\n\n this._input.removeEventListener('input', this._updateCells);\n this._input.removeEventListener('click', this._updateCells);\n this._input.removeEventListener('keyup', this._updateCells);\n this._input.removeEventListener('focus', this._scheduleUpdateCells);\n this._input.removeEventListener('blur', this._clearCells);\n\n // Restore input to direct child\n this._container.replaceWith(this._input);\n this._separatorEl?.remove();\n\n this._cells = [];\n this._separatorEl = null;\n this._initialized = false;\n }\n\n // --- Cell updates ---\n\n private _updateCells = (): void => {\n const value = this._input.value;\n const maxLen = this._input.maxLength || 6;\n const pos = Math.min(this._input.selectionStart ?? 0, maxLen - 1);\n const isFocused = document.activeElement === this._input;\n\n for (let i = 0; i < this._cells.length; i++) {\n const cell = this._cells[i];\n const span = cell.firstElementChild as HTMLSpanElement;\n const char = value[i] ?? '';\n\n span.textContent = char;\n\n if (char) {\n cell.setAttribute('data-filled', '');\n } else {\n cell.removeAttribute('data-filled');\n }\n\n if (isFocused && i === pos) {\n cell.setAttribute('data-active', '');\n } else {\n cell.removeAttribute('data-active');\n }\n }\n };\n\n private _clearCells = (): void => {\n for (const cell of this._cells) {\n cell.removeAttribute('data-active');\n }\n };\n\n private _scheduleUpdateCells = (): void => {\n requestAnimationFrame(this._updateCells);\n };\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"input-otp.js","names":[],"sources":["../../../src/html/elements/input-otp/input-otp.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\n\n/**\n * Enhances a child `<input>` with visual digit cells (Stripe-style OTP input).\n *\n * A single hidden `<input>` handles keyboard, paste, and autocomplete.\n * Visual cells are rendered as real DOM elements with individual borders and focus ring.\n *\n * @summary Stripe-style OTP input with visual digit cells over a hidden native input.\n * @customElement l-input-otp\n *\n * @attribute size - sm | lg — Cell size. Default is md.\n *\n * @cssproperty --digits - Number of digit boxes (default: 6). Must match input's maxlength.\n * @cssproperty --cell-size - Cell width and height (default: 2.75rem). Font size scales automatically.\n * @cssproperty --cell-gap - Space between cells (default: 0.5rem).\n * @cssproperty --cell-bg-color - Cell background color.\n * @cssproperty --cell-border-color - Cell border color.\n * @cssproperty --cell-border-radius - Cell border-radius.\n * @cssproperty --cell-focus-color - Border + ring color of the active (focused) cell.\n * @cssproperty --cell-focus-ring - `box-shadow` of the active cell ring (defaults to a 1px solid ring; set to `none` to disable).\n */\nexport class InputOtp extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n /** Position after which to insert a visual separator (e.g., 3 for a 3-3 grouping). */\n @property({ type: Number, reflect: true, attribute: 'separator-after' })\n separatorAfter?: number;\n\n private _input!: HTMLInputElement;\n private _container!: HTMLDivElement;\n private _cells: HTMLDivElement[] = [];\n private _separatorEl: HTMLSpanElement | null = null;\n private _initialized = false;\n\n override connectedCallback() {\n super.connectedCallback();\n requestAnimationFrame(() => this._setup());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n const input = this.querySelector<HTMLInputElement>('input');\n if (!input) return;\n\n this._input = input;\n\n // Derive digit count from --digits CSS custom property (default 6)\n const digits = Number(getComputedStyle(this).getPropertyValue('--digits').trim()) || 6;\n\n // Set sensible defaults — author can still override via HTML attributes\n const defaults: Record<string, string> = {\n type: 'text',\n inputmode: 'numeric',\n autocomplete: 'one-time-code',\n maxlength: String(digits),\n pattern: String.raw`\\d{${digits}}`,\n };\n for (const [attr, value] of Object.entries(defaults)) {\n if (!this._input.hasAttribute(attr)) {\n this._input.setAttribute(attr, value);\n }\n }\n\n // Build visual cells container\n this._container = document.createElement('div');\n this._container.className = 'l-input-otp-cells';\n this._container.setAttribute('aria-hidden', 'true');\n\n for (let i = 0; i < digits; i++) {\n const cell = document.createElement('div');\n cell.className = 'l-input-otp-cell';\n cell.appendChild(document.createElement('span'));\n this._cells.push(cell);\n this._container.appendChild(cell);\n\n // Insert separator after the specified position\n if (this.separatorAfter && i === this.separatorAfter - 1 && i < digits - 1) {\n this._separatorEl = document.createElement('span');\n this._separatorEl.className = 'l-input-otp-separator';\n this._container.appendChild(this._separatorEl);\n }\n }\n\n // Wrap: insert container before input, then move input inside\n this._input.replaceWith(this._container);\n this._container.appendChild(this._input);\n this._initialized = true;\n\n // Populate cells if input already has a value (e.g. disabled with prefilled value)\n this._updateCells();\n\n // Events — focus is deferred so it runs after the click that triggered it\n // (otherwise selectionStart is stale and the active cell flickers).\n this._input.addEventListener('input', this._updateCells);\n this._input.addEventListener('click', this._updateCells);\n this._input.addEventListener('keyup', this._updateCells);\n this._input.addEventListener('focus', this._scheduleUpdateCells);\n this._input.addEventListener('blur', this._clearCells);\n }\n\n private _teardown() {\n if (!this._initialized) return;\n\n this._input.removeEventListener('input', this._updateCells);\n this._input.removeEventListener('click', this._updateCells);\n this._input.removeEventListener('keyup', this._updateCells);\n this._input.removeEventListener('focus', this._scheduleUpdateCells);\n this._input.removeEventListener('blur', this._clearCells);\n\n // Restore input to direct child\n this._container.replaceWith(this._input);\n this._separatorEl?.remove();\n\n this._cells = [];\n this._separatorEl = null;\n this._initialized = false;\n }\n\n // --- Cell updates ---\n\n private _updateCells = (): void => {\n const value = this._input.value;\n const maxLen = this._input.maxLength || 6;\n const pos = Math.min(this._input.selectionStart ?? 0, maxLen - 1);\n const isFocused = document.activeElement === this._input;\n\n for (let i = 0; i < this._cells.length; i++) {\n const cell = this._cells[i];\n const span = cell.firstElementChild as HTMLSpanElement;\n const char = value[i] ?? '';\n\n span.textContent = char;\n\n if (char) {\n cell.setAttribute('data-filled', '');\n } else {\n cell.removeAttribute('data-filled');\n }\n\n if (isFocused && i === pos) {\n cell.setAttribute('data-active', '');\n } else {\n cell.removeAttribute('data-active');\n }\n }\n };\n\n private _clearCells = (): void => {\n for (const cell of this._cells) {\n cell.removeAttribute('data-active');\n }\n };\n\n private _scheduleUpdateCells = (): void => {\n requestAnimationFrame(this._updateCells);\n };\n}\n"],"mappings":"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"}
|
|
@@ -17,6 +17,8 @@ export type InputStepperSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
|
17
17
|
*
|
|
18
18
|
* @cssproperty --border-color - Border color of the stepper container (default appearance) and of each button (rounded appearance). Defaults to `--l-color-border`.
|
|
19
19
|
* @cssproperty --border-radius - Border radius of the stepper container (default appearance). Defaults to `--radius-md`.
|
|
20
|
+
*
|
|
21
|
+
* @customElement l-input-stepper
|
|
20
22
|
*/
|
|
21
23
|
export declare class InputStepper extends LuxenElement {
|
|
22
24
|
createRenderRoot(): this;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-stepper.d.ts","sourceRoot":"","sources":["../../../src/html/elements/input-stepper/input-stepper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"input-stepper.d.ts","sourceRoot":"","sources":["../../../src/html/elements/input-stepper/input-stepper.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAG7D,MAAM,MAAM,gBAAgB,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,YAAa,SAAQ,YAAY;IACnC,gBAAgB;IAIzB,wEAAwE;IAExE,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,wEAAwE;IAExE,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,kEAAkE;IAElE,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,oBAAoB;IAEpB,IAAI,EAAE,gBAAgB,CAAQ;IAE9B,iDAAiD;IAEjD,UAAU,UAAS;IAEnB,0CAA0C;IAE1C,aAAa,SAAkB;IAE/B,0CAA0C;IAE1C,aAAa,SAAiB;IAE9B,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,aAAa,CAA+B;IACpD,OAAO,CAAC,MAAM,CAA+B;IAC7C,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,eAAe,CAAS;IAEvB,iBAAiB;IAKjB,oBAAoB;IAKpB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IAS9C,sCAAsC;IACtC,SAAS;IAOT,sCAAsC;IACtC,SAAS;IAST,OAAO,CAAC,MAAM;IAsCd,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,WAAW;IAenB,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,gBAAgB;IAcxB,OAAO,CAAC,WAAW;IAUnB,OAAO,CAAC,YAAY;IAmBpB,OAAO,CAAC,mBAAmB;IAa3B,OAAO,CAAC,YAAY,CAA0B;IAC9C,OAAO,CAAC,YAAY,CAA0B;IAE9C,OAAO,CAAC,cAAc,CAWpB;CACH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{tagName as e}from"../../registry.js";import{LuxenElement as t}from"../../shared/luxen-element.js";import{i as n,t as r}from"../../chunks/decorate.js";var i=class extends t{constructor(...e){super(...e),this.size=`md`,this.withRoller=!1,this.decrementIcon=`lucide:minus`,this.incrementIcon=`lucide:plus`,this._input=null,this._decrementBtn=null,this._incrementBtn=null,this._valueWrapper=null,this._trackDisplay=null,this._track=null,this._observer=null,this._skipTransition=!1,this._onDecrement=()=>this.decrement(),this._onIncrement=()=>this.increment(),this._onInputChange=()=>{if(!this._input)return;let{min:e,max:t}=this._getConstraints(),n=Math.min(Math.max(this._input.valueAsNumber,e),t);this._input.value=String(n),this._skipTransition=!0,this._updateButtonStates(),this._updateTrack(),this.emit(`change`,{detail:{value:n}})}}createRenderRoot(){return this}connectedCallback(){super.connectedCallback(),requestAnimationFrame(()=>this._setup())}disconnectedCallback(){super.disconnectedCallback(),this._teardown()}updated(e){this._input&&(e.has(`min`)||e.has(`max`)||e.has(`step`))&&(this._syncConstraints(),this._updateButtonStates())}decrement(){if(!this._input)return;let{min:e,step:t}=this._getConstraints(),n=Math.max(this._input.valueAsNumber-t,e);this._applyValue(n)}increment(){if(!this._input)return;let{max:e,step:t}=this._getConstraints(),n=Math.min(this._input.valueAsNumber+t,e);this._applyValue(n)}_setup(){this._input=this.querySelector(`input[type="number"]`),this._input&&(this._input.inputMode=`numeric`,this._valueWrapper=document.createElement(`div`),this._valueWrapper.className=`l-input-stepper-value`,this._input.replaceWith(this._valueWrapper),this._valueWrapper.appendChild(this._input),this.withRoller&&this._buildTrack(),this._decrementBtn=this._createButton(this.decrementIcon,`Decrease value`),this._incrementBtn=this._createButton(this.incrementIcon,`Increase value`),this._valueWrapper.before(this._decrementBtn),this._valueWrapper.after(this._incrementBtn),this._decrementBtn.addEventListener(`click`,this._onDecrement),this._incrementBtn.addEventListener(`click`,this._onIncrement),this._input.addEventListener(`change`,this._onInputChange),this._observer=new MutationObserver(()=>this._updateButtonStates()),this._observer.observe(this._input,{attributes:!0,attributeFilter:[`disabled`]}),this._syncConstraints(),this._updateButtonStates(),this._updateTrack())}_teardown(){this._decrementBtn?.removeEventListener(`click`,this._onDecrement),this._incrementBtn?.removeEventListener(`click`,this._onIncrement),this._input?.removeEventListener(`change`,this._onInputChange),this._observer?.disconnect(),this._input&&this._valueWrapper&&this._valueWrapper.replaceWith(this._input),this._decrementBtn?.remove(),this._incrementBtn?.remove(),this._input=null,this._decrementBtn=null,this._incrementBtn=null,this._valueWrapper=null,this._trackDisplay=null,this._track=null,this._observer=null}_createButton(t,n){let r=document.createElement(`button`);r.type=`button`,r.setAttribute(`aria-label`,n);let i=e(`icon`);return r.innerHTML=`<${i} name="${t}"></${i}>`,r}_buildTrack(){this._valueWrapper&&(this._trackDisplay=document.createElement(`div`),this._trackDisplay.className=`l-input-stepper-track-display`,this._track=document.createElement(`div`),this._track.className=`l-input-stepper-track`,this._track.setAttribute(`aria-hidden`,`true`),this._rebuildTrackNumbers(),this._trackDisplay.appendChild(this._track),this._valueWrapper.appendChild(this._trackDisplay))}_rebuildTrackNumbers(){if(!this._track)return;let{min:e,max:t,step:n}=this._getConstraints(),r=Number.isFinite(t)?t:(this._input?.valueAsNumber??0)+100;this._track.innerHTML=``;for(let t=e;t<=r;t+=n){let e=document.createElement(`div`);e.textContent=String(t),this._track.appendChild(e)}}_getConstraints(){return{min:this.min??(Number(this._input?.getAttribute(`min`))||0),max:this.max??(this._input?.hasAttribute(`max`)?Number(this._input.getAttribute(`max`)):1/0),step:this.step??(Number(this._input?.getAttribute(`step`))||1)}}_syncConstraints(){if(!this._input)return;let{min:e,max:t,step:n}=this._getConstraints();this._input.min=String(e),Number.isFinite(t)&&(this._input.max=String(t)),this._input.step=String(n),this._rebuildTrackNumbers(),this._updateTrack()}_applyValue(e){this._input&&(this._input.value=String(e),this._updateButtonStates(),this._updateTrack(),this.emit(`change`,{detail:{value:e}}))}_updateTrack(){if(!this._track)return;let{min:e,step:t}=this._getConstraints(),n=(e-(this._input?.valueAsNumber??e))/t;this._track.style.translate=`0 calc(${n} * var(--_button-size))`,this._skipTransition&&=(this._track.style.transition=`none`,this._track.offsetHeight,this._track.style.transition=``,!1)}_updateButtonStates(){if(!this._input||!this._decrementBtn||!this._incrementBtn)return;let{min:e,max:t}=this._getConstraints(),n=this._input.valueAsNumber,r=this._input.disabled;this._decrementBtn.disabled=r||n<=e,this._incrementBtn.disabled=r||n>=t}};r([n({type:Number})],i.prototype,`min`,void 0),r([n({type:Number})],i.prototype,`max`,void 0),r([n({type:Number})],i.prototype,`step`,void 0),r([n({reflect:!0})],i.prototype,`size`,void 0),r([n({type:Boolean,reflect:!0,attribute:`with-roller`})],i.prototype,`withRoller`,void 0),r([n({attribute:`decrement-icon`})],i.prototype,`decrementIcon`,void 0),r([n({attribute:`increment-icon`})],i.prototype,`incrementIcon`,void 0);export{i as InputStepper};
|
|
2
2
|
//# sourceMappingURL=input-stepper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"input-stepper.js","names":[],"sources":["../../../src/html/elements/input-stepper/input-stepper.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\n\nexport type InputStepperSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\n/**\n * A stepper control that enhances a native `<input type=\"number\">` with\n * decrement/increment buttons and an optional animated number track.\n *\n * @link https://www.nngroup.com/articles/input-steppers/\n *\n * @example\n * ```html\n * <l-input-stepper>\n * <input type=\"number\" min=\"0\" max=\"10\" value=\"5\" />\n * </l-input-stepper>\n * ```\n *\n * @event change - Fired when the value changes. Detail: `{ value: number }`.\n *\n * @cssproperty --border-color - Border color of the stepper container (default appearance) and of each button (rounded appearance). Defaults to `--l-color-border`.\n * @cssproperty --border-radius - Border radius of the stepper container (default appearance). Defaults to `--radius-md`.\n */\nexport class InputStepper extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n /** Minimum allowed value. Falls back to the input's `min` attribute. */\n @property({ type: Number })\n min?: number;\n\n /** Maximum allowed value. Falls back to the input's `max` attribute. */\n @property({ type: Number })\n max?: number;\n\n /** Step increment. Falls back to the input's `step` attribute. */\n @property({ type: Number })\n step?: number;\n\n /** Control size. */\n @property({ reflect: true })\n size: InputStepperSize = 'md';\n\n /** Enable the animated number roller overlay. */\n @property({ type: Boolean, reflect: true, attribute: 'with-roller' })\n withRoller = false;\n\n /** Icon name for the decrement button. */\n @property({ attribute: 'decrement-icon' })\n decrementIcon = 'lucide:minus';\n\n /** Icon name for the increment button. */\n @property({ attribute: 'increment-icon' })\n incrementIcon = 'lucide:plus';\n\n private _input: HTMLInputElement | null = null;\n private _decrementBtn: HTMLButtonElement | null = null;\n private _incrementBtn: HTMLButtonElement | null = null;\n private _valueWrapper: HTMLDivElement | null = null;\n private _trackDisplay: HTMLDivElement | null = null;\n private _track: HTMLDivElement | null = null;\n private _observer: MutationObserver | null = null;\n private _skipTransition = false;\n\n override connectedCallback() {\n super.connectedCallback();\n requestAnimationFrame(() => this._setup());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n }\n\n override updated(changed: Map<string, unknown>) {\n if (!this._input) return;\n\n if (changed.has('min') || changed.has('max') || changed.has('step')) {\n this._syncConstraints();\n this._updateButtonStates();\n }\n }\n\n /** Decrease the value by one step. */\n decrement() {\n if (!this._input) return;\n const { min, step } = this._getConstraints();\n const newVal = Math.max(this._input.valueAsNumber - step, min);\n this._applyValue(newVal);\n }\n\n /** Increase the value by one step. */\n increment() {\n if (!this._input) return;\n const { max, step } = this._getConstraints();\n const newVal = Math.min(this._input.valueAsNumber + step, max);\n this._applyValue(newVal);\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n this._input = this.querySelector('input[type=\"number\"]');\n if (!this._input) return;\n\n this._input.inputMode = 'numeric';\n\n // Wrap input in value container\n this._valueWrapper = document.createElement('div');\n this._valueWrapper.className = 'l-input-stepper-value';\n this._input.replaceWith(this._valueWrapper);\n this._valueWrapper.appendChild(this._input);\n\n // Inject track overlay\n if (this.withRoller) {\n this._buildTrack();\n }\n\n // Create buttons\n this._decrementBtn = this._createButton(this.decrementIcon, 'Decrease value');\n this._incrementBtn = this._createButton(this.incrementIcon, 'Increase value');\n\n this._valueWrapper.before(this._decrementBtn);\n this._valueWrapper.after(this._incrementBtn);\n\n // Events\n this._decrementBtn.addEventListener('click', this._onDecrement);\n this._incrementBtn.addEventListener('click', this._onIncrement);\n this._input.addEventListener('change', this._onInputChange);\n\n // Observe disabled attribute on input\n this._observer = new MutationObserver(() => this._updateButtonStates());\n this._observer.observe(this._input, { attributes: true, attributeFilter: ['disabled'] });\n\n this._syncConstraints();\n this._updateButtonStates();\n this._updateTrack();\n }\n\n private _teardown() {\n this._decrementBtn?.removeEventListener('click', this._onDecrement);\n this._incrementBtn?.removeEventListener('click', this._onIncrement);\n this._input?.removeEventListener('change', this._onInputChange);\n this._observer?.disconnect();\n\n // Restore input to direct child\n if (this._input && this._valueWrapper) {\n this._valueWrapper.replaceWith(this._input);\n }\n this._decrementBtn?.remove();\n this._incrementBtn?.remove();\n\n this._input = null;\n this._decrementBtn = null;\n this._incrementBtn = null;\n this._valueWrapper = null;\n this._trackDisplay = null;\n this._track = null;\n this._observer = null;\n }\n\n // --- DOM helpers ---\n\n private _createButton(icon: string, label: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n btn.innerHTML = `<l-icon name=\"${icon}\"></l-icon>`;\n return btn;\n }\n\n private _buildTrack() {\n if (!this._valueWrapper) return;\n\n this._trackDisplay = document.createElement('div');\n this._trackDisplay.className = 'l-input-stepper-track-display';\n\n this._track = document.createElement('div');\n this._track.className = 'l-input-stepper-track';\n this._track.setAttribute('aria-hidden', 'true');\n\n this._rebuildTrackNumbers();\n this._trackDisplay.appendChild(this._track);\n this._valueWrapper.appendChild(this._trackDisplay);\n }\n\n private _rebuildTrackNumbers() {\n if (!this._track) return;\n\n const { min, max, step } = this._getConstraints();\n const effectiveMax = Number.isFinite(max) ? max : (this._input?.valueAsNumber ?? 0) + 100;\n\n this._track.innerHTML = '';\n for (let i = min; i <= effectiveMax; i += step) {\n const div = document.createElement('div');\n div.textContent = String(i);\n this._track.appendChild(div);\n }\n }\n\n // --- Constraints ---\n\n private _getConstraints() {\n const min = this.min ?? (Number(this._input?.getAttribute('min')) || 0);\n const max =\n this.max ??\n (this._input?.hasAttribute('max') ? Number(this._input.getAttribute('max')) : Infinity);\n const step = this.step ?? (Number(this._input?.getAttribute('step')) || 1);\n return { min, max, step };\n }\n\n private _syncConstraints() {\n if (!this._input) return;\n const { min, max, step } = this._getConstraints();\n\n this._input.min = String(min);\n if (Number.isFinite(max)) this._input.max = String(max);\n this._input.step = String(step);\n\n this._rebuildTrackNumbers();\n this._updateTrack();\n }\n\n // --- Value ---\n\n private _applyValue(val: number) {\n if (!this._input) return;\n this._input.value = String(val);\n this._updateButtonStates();\n this._updateTrack();\n this.emit('change', { detail: { value: val } });\n }\n\n // --- Track ---\n\n private _updateTrack() {\n if (!this._track) return;\n\n const { min, step } = this._getConstraints();\n const value = this._input?.valueAsNumber ?? min;\n const offset = (min - value) / step;\n\n this._track.style.translate = `0 calc(${offset} * var(--_button-size))`;\n\n if (this._skipTransition) {\n this._track.style.transition = 'none';\n void this._track.offsetHeight;\n this._track.style.transition = '';\n this._skipTransition = false;\n }\n }\n\n // --- Button states ---\n\n private _updateButtonStates() {\n if (!this._input || !this._decrementBtn || !this._incrementBtn) return;\n\n const { min, max } = this._getConstraints();\n const value = this._input.valueAsNumber;\n const disabled = this._input.disabled;\n\n this._decrementBtn.disabled = disabled || value <= min;\n this._incrementBtn.disabled = disabled || value >= max;\n }\n\n // --- Event handlers ---\n\n private _onDecrement = () => this.decrement();\n private _onIncrement = () => this.increment();\n\n private _onInputChange = () => {\n if (!this._input) return;\n\n const { min, max } = this._getConstraints();\n const clamped = Math.min(Math.max(this._input.valueAsNumber, min), max);\n this._input.value = String(clamped);\n\n this._skipTransition = true;\n this._updateButtonStates();\n this._updateTrack();\n this.emit('change', { detail: { value: clamped } });\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"input-stepper.js","names":[],"sources":["../../../src/html/elements/input-stepper/input-stepper.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { tagName } from '../../registry.js';\n\nexport type InputStepperSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n\n/**\n * A stepper control that enhances a native `<input type=\"number\">` with\n * decrement/increment buttons and an optional animated number track.\n *\n * @link https://www.nngroup.com/articles/input-steppers/\n *\n * @example\n * ```html\n * <l-input-stepper>\n * <input type=\"number\" min=\"0\" max=\"10\" value=\"5\" />\n * </l-input-stepper>\n * ```\n *\n * @event change - Fired when the value changes. Detail: `{ value: number }`.\n *\n * @cssproperty --border-color - Border color of the stepper container (default appearance) and of each button (rounded appearance). Defaults to `--l-color-border`.\n * @cssproperty --border-radius - Border radius of the stepper container (default appearance). Defaults to `--radius-md`.\n *\n * @customElement l-input-stepper\n */\nexport class InputStepper extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n /** Minimum allowed value. Falls back to the input's `min` attribute. */\n @property({ type: Number })\n min?: number;\n\n /** Maximum allowed value. Falls back to the input's `max` attribute. */\n @property({ type: Number })\n max?: number;\n\n /** Step increment. Falls back to the input's `step` attribute. */\n @property({ type: Number })\n step?: number;\n\n /** Control size. */\n @property({ reflect: true })\n size: InputStepperSize = 'md';\n\n /** Enable the animated number roller overlay. */\n @property({ type: Boolean, reflect: true, attribute: 'with-roller' })\n withRoller = false;\n\n /** Icon name for the decrement button. */\n @property({ attribute: 'decrement-icon' })\n decrementIcon = 'lucide:minus';\n\n /** Icon name for the increment button. */\n @property({ attribute: 'increment-icon' })\n incrementIcon = 'lucide:plus';\n\n private _input: HTMLInputElement | null = null;\n private _decrementBtn: HTMLButtonElement | null = null;\n private _incrementBtn: HTMLButtonElement | null = null;\n private _valueWrapper: HTMLDivElement | null = null;\n private _trackDisplay: HTMLDivElement | null = null;\n private _track: HTMLDivElement | null = null;\n private _observer: MutationObserver | null = null;\n private _skipTransition = false;\n\n override connectedCallback() {\n super.connectedCallback();\n requestAnimationFrame(() => this._setup());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n }\n\n override updated(changed: Map<string, unknown>) {\n if (!this._input) return;\n\n if (changed.has('min') || changed.has('max') || changed.has('step')) {\n this._syncConstraints();\n this._updateButtonStates();\n }\n }\n\n /** Decrease the value by one step. */\n decrement() {\n if (!this._input) return;\n const { min, step } = this._getConstraints();\n const newVal = Math.max(this._input.valueAsNumber - step, min);\n this._applyValue(newVal);\n }\n\n /** Increase the value by one step. */\n increment() {\n if (!this._input) return;\n const { max, step } = this._getConstraints();\n const newVal = Math.min(this._input.valueAsNumber + step, max);\n this._applyValue(newVal);\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n this._input = this.querySelector('input[type=\"number\"]');\n if (!this._input) return;\n\n this._input.inputMode = 'numeric';\n\n // Wrap input in value container\n this._valueWrapper = document.createElement('div');\n this._valueWrapper.className = 'l-input-stepper-value';\n this._input.replaceWith(this._valueWrapper);\n this._valueWrapper.appendChild(this._input);\n\n // Inject track overlay\n if (this.withRoller) {\n this._buildTrack();\n }\n\n // Create buttons\n this._decrementBtn = this._createButton(this.decrementIcon, 'Decrease value');\n this._incrementBtn = this._createButton(this.incrementIcon, 'Increase value');\n\n this._valueWrapper.before(this._decrementBtn);\n this._valueWrapper.after(this._incrementBtn);\n\n // Events\n this._decrementBtn.addEventListener('click', this._onDecrement);\n this._incrementBtn.addEventListener('click', this._onIncrement);\n this._input.addEventListener('change', this._onInputChange);\n\n // Observe disabled attribute on input\n this._observer = new MutationObserver(() => this._updateButtonStates());\n this._observer.observe(this._input, { attributes: true, attributeFilter: ['disabled'] });\n\n this._syncConstraints();\n this._updateButtonStates();\n this._updateTrack();\n }\n\n private _teardown() {\n this._decrementBtn?.removeEventListener('click', this._onDecrement);\n this._incrementBtn?.removeEventListener('click', this._onIncrement);\n this._input?.removeEventListener('change', this._onInputChange);\n this._observer?.disconnect();\n\n // Restore input to direct child\n if (this._input && this._valueWrapper) {\n this._valueWrapper.replaceWith(this._input);\n }\n this._decrementBtn?.remove();\n this._incrementBtn?.remove();\n\n this._input = null;\n this._decrementBtn = null;\n this._incrementBtn = null;\n this._valueWrapper = null;\n this._trackDisplay = null;\n this._track = null;\n this._observer = null;\n }\n\n // --- DOM helpers ---\n\n private _createButton(icon: string, label: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.setAttribute('aria-label', label);\n const iconTag = tagName('icon');\n btn.innerHTML = `<${iconTag} name=\"${icon}\"></${iconTag}>`;\n return btn;\n }\n\n private _buildTrack() {\n if (!this._valueWrapper) return;\n\n this._trackDisplay = document.createElement('div');\n this._trackDisplay.className = 'l-input-stepper-track-display';\n\n this._track = document.createElement('div');\n this._track.className = 'l-input-stepper-track';\n this._track.setAttribute('aria-hidden', 'true');\n\n this._rebuildTrackNumbers();\n this._trackDisplay.appendChild(this._track);\n this._valueWrapper.appendChild(this._trackDisplay);\n }\n\n private _rebuildTrackNumbers() {\n if (!this._track) return;\n\n const { min, max, step } = this._getConstraints();\n const effectiveMax = Number.isFinite(max) ? max : (this._input?.valueAsNumber ?? 0) + 100;\n\n this._track.innerHTML = '';\n for (let i = min; i <= effectiveMax; i += step) {\n const div = document.createElement('div');\n div.textContent = String(i);\n this._track.appendChild(div);\n }\n }\n\n // --- Constraints ---\n\n private _getConstraints() {\n const min = this.min ?? (Number(this._input?.getAttribute('min')) || 0);\n const max =\n this.max ??\n (this._input?.hasAttribute('max') ? Number(this._input.getAttribute('max')) : Infinity);\n const step = this.step ?? (Number(this._input?.getAttribute('step')) || 1);\n return { min, max, step };\n }\n\n private _syncConstraints() {\n if (!this._input) return;\n const { min, max, step } = this._getConstraints();\n\n this._input.min = String(min);\n if (Number.isFinite(max)) this._input.max = String(max);\n this._input.step = String(step);\n\n this._rebuildTrackNumbers();\n this._updateTrack();\n }\n\n // --- Value ---\n\n private _applyValue(val: number) {\n if (!this._input) return;\n this._input.value = String(val);\n this._updateButtonStates();\n this._updateTrack();\n this.emit('change', { detail: { value: val } });\n }\n\n // --- Track ---\n\n private _updateTrack() {\n if (!this._track) return;\n\n const { min, step } = this._getConstraints();\n const value = this._input?.valueAsNumber ?? min;\n const offset = (min - value) / step;\n\n this._track.style.translate = `0 calc(${offset} * var(--_button-size))`;\n\n if (this._skipTransition) {\n this._track.style.transition = 'none';\n void this._track.offsetHeight;\n this._track.style.transition = '';\n this._skipTransition = false;\n }\n }\n\n // --- Button states ---\n\n private _updateButtonStates() {\n if (!this._input || !this._decrementBtn || !this._incrementBtn) return;\n\n const { min, max } = this._getConstraints();\n const value = this._input.valueAsNumber;\n const disabled = this._input.disabled;\n\n this._decrementBtn.disabled = disabled || value <= min;\n this._incrementBtn.disabled = disabled || value >= max;\n }\n\n // --- Event handlers ---\n\n private _onDecrement = () => this.decrement();\n private _onIncrement = () => this.increment();\n\n private _onInputChange = () => {\n if (!this._input) return;\n\n const { min, max } = this._getConstraints();\n const clamped = Math.min(Math.max(this._input.valueAsNumber, min), max);\n this._input.value = String(clamped);\n\n this._skipTransition = true;\n this._updateButtonStates();\n this._updateTrack();\n this.emit('change', { detail: { value: clamped } });\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @summary Displays keyboard keys or shortcuts inline with text.
|
|
3
|
+
*
|
|
4
|
+
* @nativeElement kbd
|
|
5
|
+
* @selector .l-kbd
|
|
6
|
+
*
|
|
7
|
+
* @cssClass .l-kbd - Base class for keyboard key styling on `<kbd>` elements.
|
|
8
|
+
*
|
|
9
|
+
* @example Single key
|
|
10
|
+
* <kbd class="l-kbd">Esc</kbd>
|
|
11
|
+
*/
|
|
12
|
+
export declare class KbdMeta {
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=kbd.meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kbd.meta.d.ts","sourceRoot":"","sources":["../../../src/html/elements/kbd/kbd.meta.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;GAUG;AAEH,qBAAa,OAAO;CAAG"}
|
|
File without changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{uniqueId as e}from"../../registry.js";import{
|
|
1
|
+
import{uniqueId as e}from"../../registry.js";import{i as t}from"../../chunks/lit.js";import{a as n,t as r}from"../../chunks/lit-html.js";import{LuxenElement as i}from"../../shared/luxen-element.js";import{i as a,t as o}from"../../chunks/decorate.js";import s from"../../shared/styles/host.styles.js";import{PopoverController as c}from"../../shared/controllers/popover.js";var l=t(`:host{--background:var(--l-color-bg-surface,Canvas);--color:inherit;--border-radius:6px;--max-width:320px;--shadow:0 4px 6px -1px #00000014, 0 2px 4px -2px #0000000f;--arrow-size:8px;--show-duration:.15s;--hide-duration:.15s;--_border-color:var(--l-color-border-overlay,var(--lightningcss-light,#e5e7eb)var(--lightningcss-dark,#374151));display:contents}[popover]{inset:unset;isolation:isolate;box-sizing:border-box;width:max-content;max-width:var(--max-width);border:1px solid var(--_border-color);border-radius:var(--border-radius);background:var(--background);color:var(--color);box-shadow:var(--shadow);font-size:.875rem;line-height:1.5;overflow:visible}:host([full-width]) [popover]{width:100vw;max-width:none}i{width:var(--arrow-size);height:var(--arrow-size);background:var(--background);z-index:-1;display:block;position:absolute;transform:rotate(45deg)}:host([data-placement^=top]) i{border-right:1px solid var(--_border-color);border-bottom:1px solid var(--_border-color)}:host([data-placement^=bottom]) i{border-top:1px solid var(--_border-color);border-left:1px solid var(--_border-color)}:host([data-placement^=left]) i{border-right:1px solid var(--_border-color);border-top:1px solid var(--_border-color)}:host([data-placement^=right]) i{border-left:1px solid var(--_border-color);border-bottom:1px solid var(--_border-color)}`),u=class extends i{constructor(...t){super(...t),this._popoverId=e(`popover`),this._floating=new c(this,{getTriggerElement:()=>this._trigger,getFloatingElement:()=>this._popoverEl,getArrowElement:()=>this._arrowEl,onPlacementChange:e=>{this.dataset.placement=e}}),this.#e=``,this.#t=`bottom`,this.#n=8,this.#r=!1,this.#i=!1,this.#a=!1,this.#o=`click`,this._onPointerEnter=()=>{this._hasTrigger(`hover`)&&(this._floating.cleanupSafePolygon(),this.show())},this._onPointerLeave=e=>{!this._hasTrigger(`hover`)||!this.open||this._floating.handlePointerLeave(e,()=>this.hide())},this._onFocusIn=()=>{this._hasTrigger(`focus`)&&this.show()},this._onFocusOut=()=>{this._hasTrigger(`focus`)&&this.hide()},this._onClick=()=>{this._hasTrigger(`click`)&&this.toggle()},this._onKeyDown=e=>{this.open&&e.key===`Escape`&&(e.stopPropagation(),this.hide())},this._onToggle=e=>{e.newState===`closed`&&this.open&&(this.open=!1)}}static{this.styles=[s,l]}#e;get for(){return this.#e}set for(e){this.#e=e}#t;get placement(){return this.#t}set placement(e){this.#t=e}#n;get distance(){return this.#n}set distance(e){this.#n=e}#r;get open(){return this.#r}set open(e){this.#r=e}#i;get withoutArrow(){return this.#i}set withoutArrow(e){this.#i=e}#a;get fullWidth(){return this.#a}set fullWidth(e){this.#a=e}#o;get trigger(){return this.#o}set trigger(e){this.#o=e}_hasTrigger(e){return this.trigger.split(` `).includes(e)}get _trigger(){return this.for?this.getRootNode().getElementById(this.for):null}get _popoverEl(){return this.shadowRoot.querySelector(`[popover]`)}get _arrowEl(){return this.withoutArrow?null:this.shadowRoot.querySelector(`i`)}_getDuration(e){let t=parseFloat(getComputedStyle(this).getPropertyValue(e));return Number.isNaN(t)?150:t}connectedCallback(){super.connectedCallback(),requestAnimationFrame(()=>this._addTriggerListeners())}disconnectedCallback(){super.disconnectedCallback(),this._removeTriggerListeners()}updated(e){e.has(`open`)&&this._handleOpenChange(),e.has(`for`)&&(this._removeTriggerListeners(e.get(`for`)),this._addTriggerListeners())}show(){this.open||=!0}hide(){this.open&&=!1}toggle(){this.open=!this.open}async _handleOpenChange(){let e=this._popoverEl;if(!e)return;let t={placement:this.placement,distance:this.distance,fullWidth:this.fullWidth};if(this.open){if(e.showPopover(),await this._floating.updatePosition(t),!this.open)return;await this._floating.animateShow(e,this._getDuration(`--show-duration`)),this._floating.startPositioning(t),this._trigger?.setAttribute(`aria-expanded`,`true`),this._trigger?.setAttribute(`aria-controls`,this._popoverId)}else this._floating.stopPositioning(),this._floating.cleanupSafePolygon(),this._trigger?.setAttribute(`aria-expanded`,`false`),this._trigger?.removeAttribute(`aria-controls`),await this._floating.animateHide(e,this._getDuration(`--hide-duration`)),e.matches(`:popover-open`)&&e.hidePopover()}_addTriggerListeners(){this._floating.addTriggerListeners({onPointerEnter:this._onPointerEnter,onPointerLeave:this._onPointerLeave,onFocusIn:this._onFocusIn,onFocusOut:this._onFocusOut,onClick:this._onClick,onKeyDown:this._onKeyDown})}_removeTriggerListeners(e){let t=e?this.getRootNode().getElementById(e):void 0;this._floating.removeTriggerListeners(t)}render(){return n`
|
|
2
2
|
<div
|
|
3
3
|
id=${this._popoverId}
|
|
4
4
|
popover="auto"
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"popover.js","names":[],"sources":["../../../src/html/elements/popover/popover.css?inline","../../../src/html/elements/popover/popover.ts"],"sourcesContent":[":host {\n --background: var(--l-color-bg-surface, Canvas);\n --color: inherit;\n --border-radius: 6px;\n --max-width: 320px;\n --shadow: 0 4px 6px -1px rgb(0 0 0 / 8%), 0 2px 4px -2px rgb(0 0 0 / 6%);\n --arrow-size: 8px;\n --show-duration: 150ms;\n --hide-duration: 150ms;\n\n --_border-color: var(--l-color-border-overlay, light-dark(#e5e7eb, #374151));\n\n display: contents;\n}\n\n[popover] {\n inset: unset;\n overflow: visible;\n isolation: isolate;\n box-sizing: border-box;\n width: max-content;\n max-width: var(--max-width);\n border: 1px solid var(--_border-color);\n border-radius: var(--border-radius);\n background: var(--background);\n color: var(--color);\n font-size: 0.875rem;\n line-height: 1.5;\n box-shadow: var(--shadow);\n}\n\n:host([full-width]) [popover] {\n width: 100vw;\n max-width: none;\n}\n\ni {\n position: absolute;\n display: block;\n width: var(--arrow-size);\n height: var(--arrow-size);\n background: var(--background);\n transform: rotate(45deg);\n z-index: -1;\n}\n\n:host([data-placement^='top']) i {\n border-right: 1px solid var(--_border-color);\n border-bottom: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='bottom']) i {\n border-top: 1px solid var(--_border-color);\n border-left: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='left']) i {\n border-right: 1px solid var(--_border-color);\n border-top: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='right']) i {\n border-left: 1px solid var(--_border-color);\n border-bottom: 1px solid var(--_border-color);\n}\n","import { html, nothing, unsafeCSS, type PropertyValues } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { property } from 'lit/decorators.js';\nimport type { Placement } from '@floating-ui/dom';\nimport { PopoverController } from '../../shared/controllers/popover.js';\nimport { uniqueId } from '../../registry.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './popover.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * @summary A popover that displays interactive content anchored to a trigger.\n * @customElement l-popover\n *\n * @slot - Popover content.\n *\n * @csspart body - The popover container.\n * @csspart arrow - The directional arrow element.\n *\n * @cssproperty --background - Background color. Default: `Canvas`.\n * @cssproperty --color - Text color. Default: inherited.\n * @cssproperty --border-radius - Border radius. Default `8px`.\n * @cssproperty --max-width - Maximum width. Default `320px`.\n * @cssproperty --shadow - Box shadow.\n * @cssproperty --arrow-size - Arrow size. Default `8px`.\n * @cssproperty --show-duration - Show animation duration. Default `150ms`.\n * @cssproperty --hide-duration - Hide animation duration. Default `150ms`.\n */\nexport class Popover extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n private _popoverId = uniqueId('popover');\n\n private _floating = new PopoverController(this, {\n getTriggerElement: () => this._trigger,\n getFloatingElement: () => this._popoverEl,\n getArrowElement: () => this._arrowEl,\n onPlacementChange: (p) => {\n this.dataset.placement = p;\n },\n });\n\n /** The HTML id of the element triggering the popover. */\n @property()\n accessor for = '';\n\n /** The preferred placement of the popover. */\n @property()\n accessor placement: Placement = 'bottom';\n\n /** The distance in pixels from the target element. */\n @property({ type: Number })\n accessor distance = 8;\n\n /** Whether or not the popover is visible. */\n @property({ type: Boolean, reflect: true })\n accessor open = false;\n\n /** Hide the directional arrow. */\n @property({ type: Boolean, reflect: true, attribute: 'without-arrow' })\n accessor withoutArrow = false;\n\n /** Stretch the popover to the viewport width. Useful for mega menus. */\n @property({ type: Boolean, reflect: true, attribute: 'full-width' })\n accessor fullWidth = false;\n\n /** Space-separated list of trigger modes: `click`, `hover`, `focus`, `manual`. */\n @property()\n accessor trigger = 'click';\n\n private _hasTrigger(type: string) {\n return this.trigger.split(' ').includes(type);\n }\n\n private get _trigger(): HTMLElement | null {\n return this.for ? (this.getRootNode() as Document | ShadowRoot).getElementById(this.for) : null;\n }\n\n private get _popoverEl(): HTMLElement {\n return this.shadowRoot!.querySelector('[popover]')!;\n }\n\n private get _arrowEl(): HTMLElement | null {\n return this.withoutArrow ? null : this.shadowRoot!.querySelector('i');\n }\n\n private _getDuration(prop: '--show-duration' | '--hide-duration'): number {\n const parsed = parseFloat(getComputedStyle(this).getPropertyValue(prop));\n return Number.isNaN(parsed) ? 150 : parsed;\n }\n\n override connectedCallback() {\n super.connectedCallback();\n requestAnimationFrame(() => this._addTriggerListeners());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._removeTriggerListeners();\n }\n\n override updated(changed: PropertyValues<this>) {\n if (changed.has('open')) {\n void this._handleOpenChange();\n }\n if (changed.has('for')) {\n this._removeTriggerListeners(changed.get('for') as string);\n this._addTriggerListeners();\n }\n }\n\n show() {\n if (!this.open) this.open = true;\n }\n\n hide() {\n if (this.open) this.open = false;\n }\n\n toggle() {\n this.open = !this.open;\n }\n\n private async _handleOpenChange() {\n const popover = this._popoverEl;\n if (!popover) return;\n\n const posOpts = {\n placement: this.placement,\n distance: this.distance,\n fullWidth: this.fullWidth,\n };\n\n if (this.open) {\n popover.showPopover();\n await this._floating.updatePosition(posOpts);\n if (!this.open) return;\n await this._floating.animateShow(popover, this._getDuration('--show-duration'));\n this._floating.startPositioning(posOpts);\n this._trigger?.setAttribute('aria-expanded', 'true');\n this._trigger?.setAttribute('aria-controls', this._popoverId);\n } else {\n this._floating.stopPositioning();\n this._floating.cleanupSafePolygon();\n this._trigger?.setAttribute('aria-expanded', 'false');\n this._trigger?.removeAttribute('aria-controls');\n await this._floating.animateHide(popover, this._getDuration('--hide-duration'));\n if (popover.matches(':popover-open')) popover.hidePopover();\n }\n }\n\n // --- Trigger event handlers ---\n\n private _onPointerEnter = () => {\n if (!this._hasTrigger('hover')) return;\n this._floating.cleanupSafePolygon();\n this.show();\n };\n\n private _onPointerLeave = (e: PointerEvent) => {\n if (!this._hasTrigger('hover') || !this.open) return;\n this._floating.handlePointerLeave(e, () => this.hide());\n };\n\n private _onFocusIn = () => {\n if (this._hasTrigger('focus')) this.show();\n };\n private _onFocusOut = () => {\n if (this._hasTrigger('focus')) this.hide();\n };\n private _onClick = () => {\n if (this._hasTrigger('click')) this.toggle();\n };\n\n private _onKeyDown = (e: KeyboardEvent) => {\n if (this.open && e.key === 'Escape') {\n e.stopPropagation();\n this.hide();\n }\n };\n\n /** Sync `open` when popover=\"auto\" light-dismiss fires. */\n private _onToggle = (e: Event) => {\n const toggleEvent = e as ToggleEvent;\n if (toggleEvent.newState === 'closed' && this.open) {\n this.open = false;\n }\n };\n\n private _addTriggerListeners() {\n this._floating.addTriggerListeners({\n onPointerEnter: this._onPointerEnter,\n onPointerLeave: this._onPointerLeave,\n onFocusIn: this._onFocusIn,\n onFocusOut: this._onFocusOut,\n onClick: this._onClick,\n onKeyDown: this._onKeyDown,\n });\n }\n\n private _removeTriggerListeners(forId?: string) {\n const trigger = forId\n ? (this.getRootNode() as Document | ShadowRoot).getElementById(forId)\n : undefined;\n this._floating.removeTriggerListeners(trigger);\n }\n\n override render() {\n return html`\n <div\n id=${this._popoverId}\n popover=\"auto\"\n part=\"body\"\n @toggle=${this._onToggle}\n >\n ${this.withoutArrow\n ? nothing\n : html`\n <i\n part=\"arrow\"\n role=\"presentation\"\n ></i>\n `}\n <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":"8UCSA,IAAM,EAAS,EAAU,+zCAAU,CAoBtB,EAAb,cAA6B,CAAa,+CAGnB,EAAS,UAAU,gBAEpB,IAAI,EAAkB,KAAM,CAC9C,sBAAyB,KAAK,SAC9B,uBAA0B,KAAK,WAC/B,oBAAuB,KAAK,SAC5B,kBAAoB,GAAM,CACxB,KAAK,QAAQ,UAAY,GAE5B,CAAC,SAIa,WAIiB,iBAIZ,UAIJ,WAIQ,WAIH,WAIF,iCAqFa,CACzB,KAAK,YAAY,QAAQ,GAC9B,KAAK,UAAU,oBAAoB,CACnC,KAAK,MAAM,wBAGc,GAAoB,CACzC,CAAC,KAAK,YAAY,QAAQ,EAAI,CAAC,KAAK,MACxC,KAAK,UAAU,mBAAmB,MAAS,KAAK,MAAM,CAAC,sBAG9B,CACrB,KAAK,YAAY,QAAQ,EAAE,KAAK,MAAM,uBAEhB,CACtB,KAAK,YAAY,QAAQ,EAAE,KAAK,MAAM,oBAEnB,CACnB,KAAK,YAAY,QAAQ,EAAE,KAAK,QAAQ,kBAGxB,GAAqB,CACrC,KAAK,MAAQ,EAAE,MAAQ,WACzB,EAAE,iBAAiB,CACnB,KAAK,MAAM,kBAKM,GAAa,CAE5B,EAAY,WAAa,UAAY,KAAK,OAC5C,KAAK,KAAO,wBA5JS,CAAC,EAAY,EAAO,QAepC,KAAA,4CAIA,WAAA,kDAIA,UAAA,iDAIA,MAAA,6CAIA,cAAA,qDAIA,WAAA,kDAIA,SAAA,yCAET,YAAoB,EAAc,CAChC,OAAO,KAAK,QAAQ,MAAM,IAAI,CAAC,SAAS,EAAK,CAG/C,IAAY,UAA+B,CACzC,OAAO,KAAK,IAAO,KAAK,aAAa,CAA2B,eAAe,KAAK,IAAI,CAAG,KAG7F,IAAY,YAA0B,CACpC,OAAO,KAAK,WAAY,cAAc,YAAY,CAGpD,IAAY,UAA+B,CACzC,OAAO,KAAK,aAAe,KAAO,KAAK,WAAY,cAAc,IAAI,CAGvE,aAAqB,EAAqD,CACxE,IAAM,EAAS,WAAW,iBAAiB,KAAK,CAAC,iBAAiB,EAAK,CAAC,CACxE,OAAO,OAAO,MAAM,EAAO,CAAG,IAAM,EAGtC,mBAA6B,CAC3B,MAAM,mBAAmB,CACzB,0BAA4B,KAAK,sBAAsB,CAAC,CAG1D,sBAAgC,CAC9B,MAAM,sBAAsB,CAC5B,KAAK,yBAAyB,CAGhC,QAAiB,EAA+B,CAC1C,EAAQ,IAAI,OAAO,EACrB,KAAU,mBAAmB,CAE3B,EAAQ,IAAI,MAAM,GACpB,KAAK,wBAAwB,EAAQ,IAAI,MAAM,CAAW,CAC1D,KAAK,sBAAsB,EAI/B,MAAO,CACL,AAAgB,KAAK,OAAO,GAG9B,MAAO,CACL,AAAe,KAAK,OAAO,GAG7B,QAAS,CACP,KAAK,KAAO,CAAC,KAAK,KAGpB,MAAc,mBAAoB,CAChC,IAAM,EAAU,KAAK,WACrB,GAAI,CAAC,EAAS,OAEd,IAAM,EAAU,CACd,UAAW,KAAK,UAChB,SAAU,KAAK,SACf,UAAW,KAAK,UACjB,CAED,GAAI,KAAK,KAAM,CAGb,GAFA,EAAQ,aAAa,CACrB,MAAM,KAAK,UAAU,eAAe,EAAQ,CACxC,CAAC,KAAK,KAAM,OAChB,MAAM,KAAK,UAAU,YAAY,EAAS,KAAK,aAAa,kBAAkB,CAAC,CAC/E,KAAK,UAAU,iBAAiB,EAAQ,CACxC,KAAK,UAAU,aAAa,gBAAiB,OAAO,CACpD,KAAK,UAAU,aAAa,gBAAiB,KAAK,WAAW,MAE7D,KAAK,UAAU,iBAAiB,CAChC,KAAK,UAAU,oBAAoB,CACnC,KAAK,UAAU,aAAa,gBAAiB,QAAQ,CACrD,KAAK,UAAU,gBAAgB,gBAAgB,CAC/C,MAAM,KAAK,UAAU,YAAY,EAAS,KAAK,aAAa,kBAAkB,CAAC,CAC3E,EAAQ,QAAQ,gBAAgB,EAAE,EAAQ,aAAa,CA0C/D,sBAA+B,CAC7B,KAAK,UAAU,oBAAoB,CACjC,eAAgB,KAAK,gBACrB,eAAgB,KAAK,gBACrB,UAAW,KAAK,WAChB,WAAY,KAAK,YACjB,QAAS,KAAK,SACd,UAAW,KAAK,WACjB,CAAC,CAGJ,wBAAgC,EAAgB,CAC9C,IAAM,EAAU,EACX,KAAK,aAAa,CAA2B,eAAe,EAAM,CACnE,IAAA,GACJ,KAAK,UAAU,uBAAuB,EAAQ,CAGhD,QAAkB,CAChB,MAAO,EAAI;;aAEF,KAAK,WAAW;;;kBAGX,KAAK,UAAU;;UAEvB,KAAK,aACH,EACA,CAAI;;;;;cAKF;;;WAnLX,GAAU,CAAA,CAAA,EAAA,UAAA,MAAA,KAAA,IAIV,GAAU,CAAA,CAAA,EAAA,UAAA,YAAA,KAAA,IAIV,EAAS,CAAE,KAAM,OAAQ,CAAC,CAAA,CAAA,EAAA,UAAA,WAAA,KAAA,IAI1B,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,CAAC,CAAA,CAAA,EAAA,UAAA,OAAA,KAAA,IAI1C,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,UAAW,gBAAiB,CAAC,CAAA,CAAA,EAAA,UAAA,eAAA,KAAA,IAItE,EAAS,CAAE,KAAM,QAAS,QAAS,GAAM,UAAW,aAAc,CAAC,CAAA,CAAA,EAAA,UAAA,YAAA,KAAA,IAInE,GAAU,CAAA,CAAA,EAAA,UAAA,UAAA,KAAA"}
|
|
1
|
+
{"version":3,"file":"popover.js","names":[],"sources":["../../../src/html/elements/popover/popover.css?inline","../../../src/html/elements/popover/popover.ts"],"sourcesContent":[":host {\n --background: var(--l-color-bg-surface, Canvas);\n --color: inherit;\n --border-radius: 6px;\n --max-width: 320px;\n --shadow: 0 4px 6px -1px rgb(0 0 0 / 8%), 0 2px 4px -2px rgb(0 0 0 / 6%);\n --arrow-size: 8px;\n --show-duration: 150ms;\n --hide-duration: 150ms;\n\n --_border-color: var(--l-color-border-overlay, light-dark(#e5e7eb, #374151));\n\n display: contents;\n}\n\n[popover] {\n inset: unset;\n overflow: visible;\n isolation: isolate;\n box-sizing: border-box;\n width: max-content;\n max-width: var(--max-width);\n border: 1px solid var(--_border-color);\n border-radius: var(--border-radius);\n background: var(--background);\n color: var(--color);\n font-size: 0.875rem;\n line-height: 1.5;\n box-shadow: var(--shadow);\n}\n\n:host([full-width]) [popover] {\n width: 100vw;\n max-width: none;\n}\n\ni {\n position: absolute;\n display: block;\n width: var(--arrow-size);\n height: var(--arrow-size);\n background: var(--background);\n transform: rotate(45deg);\n z-index: -1;\n}\n\n:host([data-placement^='top']) i {\n border-right: 1px solid var(--_border-color);\n border-bottom: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='bottom']) i {\n border-top: 1px solid var(--_border-color);\n border-left: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='left']) i {\n border-right: 1px solid var(--_border-color);\n border-top: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='right']) i {\n border-left: 1px solid var(--_border-color);\n border-bottom: 1px solid var(--_border-color);\n}\n","import { html, nothing, unsafeCSS, type PropertyValues } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { property } from 'lit/decorators.js';\nimport type { Placement } from '@floating-ui/dom';\nimport { PopoverController } from '../../shared/controllers/popover.js';\nimport { uniqueId } from '../../registry.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './popover.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * @summary A popover that displays interactive content anchored to a trigger.\n * @customElement l-popover\n *\n * @slot - Popover content.\n *\n * @csspart body - The popover container.\n * @csspart arrow - The directional arrow element.\n *\n * @cssproperty --background - Background color. Default: `Canvas`.\n * @cssproperty --color - Text color. Default: inherited.\n * @cssproperty --border-radius - Border radius. Default `8px`.\n * @cssproperty --max-width - Maximum width. Default `320px`.\n * @cssproperty --shadow - Box shadow.\n * @cssproperty --arrow-size - Arrow size. Default `8px`.\n * @cssproperty --show-duration - Show animation duration. Default `150ms`.\n * @cssproperty --hide-duration - Hide animation duration. Default `150ms`.\n */\nexport class Popover extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n private _popoverId = uniqueId('popover');\n\n private _floating = new PopoverController(this, {\n getTriggerElement: () => this._trigger,\n getFloatingElement: () => this._popoverEl,\n getArrowElement: () => this._arrowEl,\n onPlacementChange: (p) => {\n this.dataset.placement = p;\n },\n });\n\n /** The HTML id of the element triggering the popover. */\n @property()\n accessor for = '';\n\n /** The preferred placement of the popover. */\n @property()\n accessor placement: Placement = 'bottom';\n\n /** The distance in pixels from the target element. */\n @property({ type: Number })\n accessor distance = 8;\n\n /** Whether or not the popover is visible. */\n @property({ type: Boolean, reflect: true })\n accessor open = false;\n\n /** Hide the directional arrow. */\n @property({ type: Boolean, reflect: true, attribute: 'without-arrow' })\n accessor withoutArrow = false;\n\n /** Stretch the popover to the viewport width. Useful for mega menus. */\n @property({ type: Boolean, reflect: true, attribute: 'full-width' })\n accessor fullWidth = false;\n\n /** Space-separated list of trigger modes: `click`, `hover`, `focus`, `manual`. */\n @property()\n accessor trigger = 'click';\n\n private _hasTrigger(type: string) {\n return this.trigger.split(' ').includes(type);\n }\n\n private get _trigger(): HTMLElement | null {\n return this.for ? (this.getRootNode() as Document | ShadowRoot).getElementById(this.for) : null;\n }\n\n private get _popoverEl(): HTMLElement {\n return this.shadowRoot!.querySelector('[popover]')!;\n }\n\n private get _arrowEl(): HTMLElement | null {\n return this.withoutArrow ? null : this.shadowRoot!.querySelector('i');\n }\n\n private _getDuration(prop: '--show-duration' | '--hide-duration'): number {\n const parsed = parseFloat(getComputedStyle(this).getPropertyValue(prop));\n return Number.isNaN(parsed) ? 150 : parsed;\n }\n\n override connectedCallback() {\n super.connectedCallback();\n requestAnimationFrame(() => this._addTriggerListeners());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._removeTriggerListeners();\n }\n\n override updated(changed: PropertyValues<this>) {\n if (changed.has('open')) {\n void this._handleOpenChange();\n }\n if (changed.has('for')) {\n this._removeTriggerListeners(changed.get('for') as string);\n this._addTriggerListeners();\n }\n }\n\n show() {\n if (!this.open) this.open = true;\n }\n\n hide() {\n if (this.open) this.open = false;\n }\n\n toggle() {\n this.open = !this.open;\n }\n\n private async _handleOpenChange() {\n const popover = this._popoverEl;\n if (!popover) return;\n\n const posOpts = {\n placement: this.placement,\n distance: this.distance,\n fullWidth: this.fullWidth,\n };\n\n if (this.open) {\n popover.showPopover();\n await this._floating.updatePosition(posOpts);\n if (!this.open) return;\n await this._floating.animateShow(popover, this._getDuration('--show-duration'));\n this._floating.startPositioning(posOpts);\n this._trigger?.setAttribute('aria-expanded', 'true');\n this._trigger?.setAttribute('aria-controls', this._popoverId);\n } else {\n this._floating.stopPositioning();\n this._floating.cleanupSafePolygon();\n this._trigger?.setAttribute('aria-expanded', 'false');\n this._trigger?.removeAttribute('aria-controls');\n await this._floating.animateHide(popover, this._getDuration('--hide-duration'));\n if (popover.matches(':popover-open')) popover.hidePopover();\n }\n }\n\n // --- Trigger event handlers ---\n\n private _onPointerEnter = () => {\n if (!this._hasTrigger('hover')) return;\n this._floating.cleanupSafePolygon();\n this.show();\n };\n\n private _onPointerLeave = (e: PointerEvent) => {\n if (!this._hasTrigger('hover') || !this.open) return;\n this._floating.handlePointerLeave(e, () => this.hide());\n };\n\n private _onFocusIn = () => {\n if (this._hasTrigger('focus')) this.show();\n };\n private _onFocusOut = () => {\n if (this._hasTrigger('focus')) this.hide();\n };\n private _onClick = () => {\n if (this._hasTrigger('click')) this.toggle();\n };\n\n private _onKeyDown = (e: KeyboardEvent) => {\n if (this.open && e.key === 'Escape') {\n e.stopPropagation();\n this.hide();\n }\n };\n\n /** Sync `open` when popover=\"auto\" light-dismiss fires. */\n private _onToggle = (e: Event) => {\n const toggleEvent = e as ToggleEvent;\n if (toggleEvent.newState === 'closed' && this.open) {\n this.open = false;\n }\n };\n\n private _addTriggerListeners() {\n this._floating.addTriggerListeners({\n onPointerEnter: this._onPointerEnter,\n onPointerLeave: this._onPointerLeave,\n onFocusIn: this._onFocusIn,\n onFocusOut: this._onFocusOut,\n onClick: this._onClick,\n onKeyDown: this._onKeyDown,\n });\n }\n\n private _removeTriggerListeners(forId?: string) {\n const trigger = forId\n ? (this.getRootNode() as Document | ShadowRoot).getElementById(forId)\n : undefined;\n this._floating.removeTriggerListeners(trigger);\n }\n\n override render() {\n return html`\n <div\n id=${this._popoverId}\n popover=\"auto\"\n part=\"body\"\n @toggle=${this._onToggle}\n >\n ${this.withoutArrow\n ? nothing\n : html`\n <i\n part=\"arrow\"\n role=\"presentation\"\n ></i>\n `}\n <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @summary A progress bar built on the native `<progress>` element.
|
|
3
|
+
*
|
|
4
|
+
* @nativeElement progress
|
|
5
|
+
* @selector .l-progress
|
|
6
|
+
*
|
|
7
|
+
* @attribute value - Current progress between `0` and `1` (omit for indeterminate).
|
|
8
|
+
* @attribute data-orientation - vertical — Vertical orientation.
|
|
9
|
+
*
|
|
10
|
+
* @cssClass .l-progress - Base progress bar style.
|
|
11
|
+
*
|
|
12
|
+
* @cssproperty [--size=4px] - Bar thickness.
|
|
13
|
+
* @cssproperty --track-color - Track background color.
|
|
14
|
+
* @cssproperty --indicator-color - Fill/indicator color.
|
|
15
|
+
* @cssproperty --indeterminate-animation - Animation name for the indeterminate state.
|
|
16
|
+
*
|
|
17
|
+
* @example Determinate
|
|
18
|
+
* <progress class="l-progress" value="0.5"></progress>
|
|
19
|
+
*/
|
|
20
|
+
export declare class ProgressMeta {
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=progress.meta.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.meta.d.ts","sourceRoot":"","sources":["../../../src/html/elements/progress/progress.meta.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,qBAAa,YAAY;CAAG"}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/html/elements/prose-editor/index.ts"],"names":[],"mappings":"AAEA,cAAc,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/html/elements/prose-editor/index.ts"],"sourcesContent":["import { define } from '../../define.js';\nimport { ProseEditor } from './prose-editor.js';\nexport * from './prose-editor.js';\ndefine('prose-editor', ProseEditor);\n"],"mappings":"yFAGA,EAAO,eAAgB,EAAY"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { PropertyValues, TemplateResult } from 'lit';
|
|
2
|
+
import { Editor, JSONContent } from '@tiptap/core';
|
|
3
|
+
import { LuxenFormAssociatedElement } from '../../shared/luxen-form-associated-element.js';
|
|
4
|
+
type ToolbarCommandName = 'heading-1' | 'heading-2' | 'heading-3' | 'bold' | 'italic' | 'underline' | 'strike' | 'highlight' | 'bulletlist' | 'orderedlist' | 'blockquote' | 'code-block' | 'horizontal-rule' | 'link' | 'emoji' | 'attachment' | 'undo' | 'redo' | 'divider';
|
|
5
|
+
/**
|
|
6
|
+
* @summary A rich text editor built on Tiptap (ProseMirror). Form-associated: its value is the editor HTML.
|
|
7
|
+
* @customElement l-prose-editor
|
|
8
|
+
*
|
|
9
|
+
* @slot toolbar-start - Content placed before the generated toolbar buttons.
|
|
10
|
+
* @slot toolbar-end - Content placed after the generated toolbar buttons.
|
|
11
|
+
*
|
|
12
|
+
* @event change - Fired when the content changes. `detail` is `{ html, json }`.
|
|
13
|
+
* @event add-file - Fired when the attachment toolbar button is clicked.
|
|
14
|
+
*
|
|
15
|
+
* @csspart wrapper - The editor frame wrapping the toolbar and content.
|
|
16
|
+
* @csspart toolbar - The toolbar row.
|
|
17
|
+
* @csspart toolbar-button - Any toolbar button.
|
|
18
|
+
* @csspart divider - A toolbar divider.
|
|
19
|
+
* @csspart editor - The container around the editable content.
|
|
20
|
+
*
|
|
21
|
+
* @cssproperty --border-color - Color of the editor frame border.
|
|
22
|
+
* @cssproperty --border-width - Width of the editor frame border.
|
|
23
|
+
* @cssproperty --border-radius - Corner radius of the editor frame.
|
|
24
|
+
* @cssproperty --background - Background color of the editor.
|
|
25
|
+
* @cssproperty --color - Text color of the editor.
|
|
26
|
+
* @cssproperty --toolbar-background - Background color of the toolbar.
|
|
27
|
+
* @cssproperty --toolbar-padding - Padding around the toolbar.
|
|
28
|
+
* @cssproperty --toolbar-gap - Gap between toolbar buttons.
|
|
29
|
+
* @cssproperty --toolbar-divider-color - Color of toolbar dividers.
|
|
30
|
+
* @cssproperty --toolbar-button-size - Size of toolbar buttons.
|
|
31
|
+
* @cssproperty --toolbar-button-radius - Corner radius of toolbar buttons.
|
|
32
|
+
* @cssproperty --toolbar-button-color - Icon color of inactive toolbar buttons.
|
|
33
|
+
* @cssproperty --toolbar-button-color-active - Icon color of hovered/active toolbar buttons.
|
|
34
|
+
* @cssproperty --toolbar-button-background-hover - Background of hovered toolbar buttons.
|
|
35
|
+
* @cssproperty --toolbar-button-background-active - Background of active toolbar buttons.
|
|
36
|
+
* @cssproperty --content-padding - Padding inside the editable content region. Default `0.75rem 1rem`.
|
|
37
|
+
* @cssproperty --content-min-height - Minimum height of the editable content region. Default `8rem`.
|
|
38
|
+
* @cssproperty --placeholder-color - Placeholder text color.
|
|
39
|
+
*/
|
|
40
|
+
export declare class ProseEditor extends LuxenFormAssociatedElement {
|
|
41
|
+
static styles: import('lit').CSSResult[];
|
|
42
|
+
/** The Tiptap editor instance. Available after the first render. */
|
|
43
|
+
editor: Editor;
|
|
44
|
+
/** Initial HTML content. */
|
|
45
|
+
accessor initialHtml: string;
|
|
46
|
+
/** Initial content as a serialized ProseMirror JSON string. */
|
|
47
|
+
accessor initialJson: string;
|
|
48
|
+
/** Class applied to the `.ProseMirror` editable element (e.g. for Tailwind Typography `prose`). */
|
|
49
|
+
accessor editorClass: string;
|
|
50
|
+
/** Explicit list of toolbar commands. Overrides `toolbar-preset` when set. */
|
|
51
|
+
accessor toolbar: ToolbarCommandName[];
|
|
52
|
+
/** Built-in toolbar layout used when `toolbar` is not set. */
|
|
53
|
+
accessor toolbarPreset: 'default' | 'minimal';
|
|
54
|
+
/** Where the toolbar sits relative to the content. */
|
|
55
|
+
accessor toolbarPlacement: 'top' | 'bottom';
|
|
56
|
+
/** Focus the editor on creation. */
|
|
57
|
+
accessor autofocus: boolean;
|
|
58
|
+
/** Placeholder shown when the editor is empty. */
|
|
59
|
+
accessor placeholder: string;
|
|
60
|
+
accessor _emojiPickerActive: boolean;
|
|
61
|
+
private _editorRoot?;
|
|
62
|
+
private _emojiPicker?;
|
|
63
|
+
get validationTarget(): HTMLElement | undefined;
|
|
64
|
+
private get _toolbar();
|
|
65
|
+
firstUpdated(): void;
|
|
66
|
+
updated(changed: PropertyValues<this>): void;
|
|
67
|
+
disconnectedCallback(): void;
|
|
68
|
+
/** Get the current content as an HTML string. Empty paragraph resolves to `''`. */
|
|
69
|
+
getHTML(): string;
|
|
70
|
+
/** Get the current content as ProseMirror JSON. */
|
|
71
|
+
getJSON(): JSONContent;
|
|
72
|
+
/** Remove all content. */
|
|
73
|
+
clear(): void;
|
|
74
|
+
focus(): void;
|
|
75
|
+
blur(): void;
|
|
76
|
+
toggleBold(): void;
|
|
77
|
+
toggleItalic(): void;
|
|
78
|
+
toggleUnderline(): void;
|
|
79
|
+
toggleStrike(): void;
|
|
80
|
+
toggleHighlight(): void;
|
|
81
|
+
toggleHeading(level: 1 | 2 | 3): void;
|
|
82
|
+
toggleBulletList(): void;
|
|
83
|
+
toggleOrderedList(): void;
|
|
84
|
+
toggleBlockquote(): void;
|
|
85
|
+
toggleCodeBlock(): void;
|
|
86
|
+
setHorizontalRule(): void;
|
|
87
|
+
undo(): void;
|
|
88
|
+
redo(): void;
|
|
89
|
+
toggleLink(): void;
|
|
90
|
+
formResetCallback(): void;
|
|
91
|
+
/** Sync the form value and validity from the current content. Returns the HTML. */
|
|
92
|
+
private _syncValue;
|
|
93
|
+
private _emitChange;
|
|
94
|
+
private _initialContent;
|
|
95
|
+
/**
|
|
96
|
+
* The editable element is created in light DOM (slotted), not the shadow root.
|
|
97
|
+
* Firefox and WebKit have long-standing bugs with `contenteditable` carets and
|
|
98
|
+
* DOM selections inside a shadow tree, so ProseMirror must live outside it.
|
|
99
|
+
* @see https://bugzilla.mozilla.org/show_bug.cgi?id=1496769
|
|
100
|
+
* @see https://bugs.webkit.org/show_bug.cgi?id=163921
|
|
101
|
+
*/
|
|
102
|
+
private _createEditorRoot;
|
|
103
|
+
private _onFocus;
|
|
104
|
+
private _onKeyDown;
|
|
105
|
+
private _toggleEmojiPicker;
|
|
106
|
+
private get _emojiButton();
|
|
107
|
+
private _positionEmojiPicker;
|
|
108
|
+
private _renderButton;
|
|
109
|
+
private _renderToolbarItem;
|
|
110
|
+
render(): TemplateResult;
|
|
111
|
+
}
|
|
112
|
+
export {};
|
|
113
|
+
//# sourceMappingURL=prose-editor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prose-editor.d.ts","sourceRoot":"","sources":["../../../src/html/elements/prose-editor/prose-editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAa,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAO1E,OAAO,EAAE,MAAM,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAIxD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAE3F,OAAO,kBAAkB,CAAC;AAK1B,KAAK,kBAAkB,GACnB,WAAW,GACX,WAAW,GACX,WAAW,GACX,MAAM,GACN,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,WAAW,GACX,YAAY,GACZ,aAAa,GACb,YAAY,GACZ,YAAY,GACZ,iBAAiB,GACjB,MAAM,GACN,OAAO,GACP,YAAY,GACZ,MAAM,GACN,MAAM,GACN,SAAS,CAAC;AA2Bd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,qBAAa,WAAY,SAAQ,0BAA0B;IACzD,OAAgB,MAAM,4BAAwB;IAE9C,oEAAoE;IACpE,MAAM,EAAG,MAAM,CAAC;IAEhB,4BAA4B;IAE5B,QAAQ,CAAC,WAAW,SAAM;IAE1B,+DAA+D;IAE/D,QAAQ,CAAC,WAAW,SAAM;IAE1B,mGAAmG;IAEnG,QAAQ,CAAC,WAAW,SAAW;IAE/B,8EAA8E;IAO9E,QAAQ,CAAC,OAAO,EAAE,kBAAkB,EAAE,CAAM;IAE5C,8DAA8D;IAE9D,QAAQ,CAAC,aAAa,EAAE,SAAS,GAAG,SAAS,CAAa;IAE1D,sDAAsD;IAEtD,QAAQ,CAAC,gBAAgB,EAAE,KAAK,GAAG,QAAQ,CAAS;IAEpD,oCAAoC;IAEpC,QAAQ,CAAC,SAAS,UAAS;IAE3B,kDAAkD;IAElD,QAAQ,CAAC,WAAW,SAAM;IAG1B,QAAQ,CAAC,kBAAkB,UAAS;IAEpC,OAAO,CAAC,WAAW,CAAC,CAAiB;IACrC,OAAO,CAAC,YAAY,CAAC,CAAc;IAEnC,IAAa,gBAAgB,IAAI,WAAW,GAAG,SAAS,CAEvD;IAED,OAAO,KAAK,QAAQ,GAEnB;IAEQ,YAAY;IA4BZ,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC;IASrC,oBAAoB;IAW7B,mFAAmF;IACnF,OAAO,IAAI,MAAM;IAMjB,mDAAmD;IACnD,OAAO,IAAI,WAAW;IAItB,0BAA0B;IAC1B,KAAK;IAII,KAAK;IAIL,IAAI;IAIb,UAAU;IAIV,YAAY;IAIZ,eAAe;IAIf,YAAY;IAIZ,eAAe;IAIf,aAAa,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;IAI9B,gBAAgB;IAIhB,iBAAiB;IAIjB,gBAAgB;IAIhB,eAAe;IAIf,iBAAiB;IAIjB,IAAI;IAIJ,IAAI;IAIJ,UAAU;IAaD,iBAAiB;IAK1B,mFAAmF;IACnF,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,eAAe;IAQvB;;;;;;OAMG;IACH,OAAO,CAAC,iBAAiB;IAQzB,OAAO,CAAC,QAAQ,CAId;IAEF,OAAO,CAAC,UAAU,CAEhB;YAIY,kBAAkB;IA0BhC,OAAO,KAAK,YAAY,GAEvB;YAEa,oBAAoB;IAwBlC,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,kBAAkB;IAwIjB,MAAM;CAyBhB"}
|