@ixfx/components 0.6.2 → 0.7.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.
Files changed (152) hide show
  1. package/bundle/index.d.ts +1490 -615
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +20477 -15855
  4. package/bundle/index.js.map +1 -1
  5. package/bundle/style.css +1 -1
  6. package/dist/ac-text.js +3 -2
  7. package/dist/ac-text.js.map +1 -1
  8. package/dist/ac-token.js +3 -2
  9. package/dist/ac-token.js.map +1 -1
  10. package/dist/{button-Bn0BuLpO.js → button-Dat2yHAU.js} +4 -3
  11. package/dist/button-Dat2yHAU.js.map +1 -0
  12. package/dist/button.js +1 -1
  13. package/dist/checkbox.js +1 -1
  14. package/dist/{colour-picker-0stHB90J.js → colour-picker-BSDBL-QL.js} +4 -3
  15. package/dist/{colour-picker-0stHB90J.js.map → colour-picker-BSDBL-QL.js.map} +1 -1
  16. package/dist/colour-picker.js +1 -1
  17. package/dist/crumbs.js +4 -2
  18. package/dist/crumbs.js.map +1 -1
  19. package/dist/data-display.js +1 -1
  20. package/dist/data-grid.js +4 -2
  21. package/dist/data-grid.js.map +1 -1
  22. package/dist/{defaults-BCiDhZbF.js → defaults-BkWCPJFL.js} +3 -20
  23. package/dist/defaults-BkWCPJFL.js.map +1 -0
  24. package/dist/editable-label-rzXkjf1H.d.ts +75 -0
  25. package/dist/editable-label-rzXkjf1H.d.ts.map +1 -0
  26. package/dist/editable-label.d.ts +2 -75
  27. package/dist/editable-label.js +2 -1
  28. package/dist/editable-label.js.map +1 -1
  29. package/dist/{fallbacks-DEE1nCTt.js → fallbacks-DNI9xt0F.js} +2 -2
  30. package/dist/{fallbacks-DEE1nCTt.js.map → fallbacks-DNI9xt0F.js.map} +1 -1
  31. package/dist/{grouped-item-lister-_pMDwIo1.d.ts → grouped-item-lister-DnWB-eFT.d.ts} +2 -2
  32. package/dist/{grouped-item-lister-_pMDwIo1.d.ts.map → grouped-item-lister-DnWB-eFT.d.ts.map} +1 -1
  33. package/dist/grouped-item-lister.d.ts +1 -1
  34. package/dist/{icons-Bm2ByQ3s.js → icon-CvnPanhA.js} +3 -6
  35. package/dist/icon-CvnPanhA.js.map +1 -0
  36. package/dist/icons.js +8 -2
  37. package/dist/icons.js.map +1 -0
  38. package/dist/index-CG2vIgPv.d.ts +101 -0
  39. package/dist/index-CG2vIgPv.d.ts.map +1 -0
  40. package/dist/index.d.ts +655 -65
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +3682 -924
  43. package/dist/index.js.map +1 -1
  44. package/dist/interaction-D5XdKzbR.js +2 -0
  45. package/dist/labelled-radial-input.js +2 -1
  46. package/dist/labelled-radial-input.js.map +1 -1
  47. package/dist/labelled-slider-input-DzigjMwP.js +808 -0
  48. package/dist/labelled-slider-input-DzigjMwP.js.map +1 -0
  49. package/dist/labelled-slider-input.d.ts +2 -0
  50. package/dist/labelled-slider-input.js +2 -0
  51. package/dist/{types-DlVNJez_.d.ts → list-selection-types-DSuRNWpx.d.ts} +10 -2
  52. package/dist/list-selection-types-DSuRNWpx.d.ts.map +1 -0
  53. package/dist/menu-BjRvlgPy.js +825 -0
  54. package/dist/menu-BjRvlgPy.js.map +1 -0
  55. package/dist/menu-item-B-zYrTTi.js +797 -0
  56. package/dist/menu-item-B-zYrTTi.js.map +1 -0
  57. package/dist/menu.js +2 -1
  58. package/dist/miller.d.ts +1 -1
  59. package/dist/miller.js +3 -2
  60. package/dist/miller.js.map +1 -1
  61. package/dist/narrowed-text.js +4 -2
  62. package/dist/narrowed-text.js.map +1 -1
  63. package/dist/notifier.js +3 -2
  64. package/dist/notifier.js.map +1 -1
  65. package/dist/panel.d.ts +13 -13
  66. package/dist/panel.d.ts.map +1 -1
  67. package/dist/panel.js +37 -253
  68. package/dist/panel.js.map +1 -1
  69. package/dist/plots.js +1 -1
  70. package/dist/polar-pad.js +1 -1
  71. package/dist/{radial-input-Dk8Wydp5.js → radial-input-Dp5qz0ly.js} +2 -2
  72. package/dist/{radial-input-Dk8Wydp5.js.map → radial-input-Dp5qz0ly.js.map} +1 -1
  73. package/dist/radial-input.js +1 -1
  74. package/dist/range-input.js +1 -1
  75. package/dist/range.js +1 -1
  76. package/dist/registry-CkW7q09Q.js +21 -0
  77. package/dist/registry-CkW7q09Q.js.map +1 -0
  78. package/dist/select-horiz.js +3 -2
  79. package/dist/select-horiz.js.map +1 -1
  80. package/dist/{slider-input-XppH3vcy.d.ts → slider-input-BfRUW2ZB.d.ts} +16 -3
  81. package/dist/slider-input-BfRUW2ZB.d.ts.map +1 -0
  82. package/dist/{slider-input-CT4gcF-o.js → slider-input-De4eoT11.js} +382 -67
  83. package/dist/slider-input-De4eoT11.js.map +1 -0
  84. package/dist/slider-input.d.ts +1 -1
  85. package/dist/slider-input.js +1 -1
  86. package/dist/snackbar.js +1 -1
  87. package/dist/split-layout-BFSbUZQv.js +969 -0
  88. package/dist/split-layout-BFSbUZQv.js.map +1 -0
  89. package/dist/split-layout-JK3xWVX2.d.ts +179 -0
  90. package/dist/split-layout-JK3xWVX2.d.ts.map +1 -0
  91. package/dist/split-layout.d.ts +2 -60
  92. package/dist/split-layout.js +1 -617
  93. package/dist/style.css +1 -1
  94. package/dist/swipe.js +1 -1
  95. package/dist/{tab-list-D_1cYhB_.d.ts → tab-list-MPwq_1Jj.d.ts} +2 -1
  96. package/dist/tab-list-MPwq_1Jj.d.ts.map +1 -0
  97. package/dist/tabs.d.ts +1 -1
  98. package/dist/tabs.js +96 -14
  99. package/dist/tabs.js.map +1 -1
  100. package/dist/{tickled-controller-BtevrRLV.d.ts → tickled-controller-CRzdIEjJ.d.ts} +7 -1
  101. package/dist/tickled-controller-CRzdIEjJ.d.ts.map +1 -0
  102. package/dist/{tickled-controller-DkAU-0qL.js → tickled-controller-h9GmJ_bU.js} +8 -2
  103. package/dist/tickled-controller-h9GmJ_bU.js.map +1 -0
  104. package/dist/titlebar-DaCfpliv.d.ts +50 -0
  105. package/dist/titlebar-DaCfpliv.d.ts.map +1 -0
  106. package/dist/titlebar.d.ts +2 -0
  107. package/dist/titlebar.js +324 -0
  108. package/dist/titlebar.js.map +1 -0
  109. package/dist/{tree-BO6BXI2b.js → tree-Ch4W8qXQ.js} +4 -3
  110. package/dist/{tree-BO6BXI2b.js.map → tree-Ch4W8qXQ.js.map} +1 -1
  111. package/dist/tree.d.ts +1 -1
  112. package/dist/tree.js +1 -1
  113. package/dist/vertical-list-ClnqTkF3.js +814 -0
  114. package/dist/vertical-list-ClnqTkF3.js.map +1 -0
  115. package/dist/vertical-list.d.ts +8 -9
  116. package/dist/vertical-list.d.ts.map +1 -1
  117. package/dist/vertical-list.js +1 -736
  118. package/dist/{xy-axis-B6yMjckW.js → xy-axis-CxHC8z5E.js} +109 -3
  119. package/dist/xy-axis-CxHC8z5E.js.map +1 -0
  120. package/dist/xy-pad.js +1 -1
  121. package/docs-user/README.md +5 -0
  122. package/docs-user/detail-list.md +398 -0
  123. package/docs-user/dock.md +310 -0
  124. package/docs-user/index.json +27 -2
  125. package/docs-user/labelled-slider-input.md +198 -0
  126. package/docs-user/llms.txt +6 -1
  127. package/docs-user/panel.md +20 -1
  128. package/docs-user/slider-input.md +55 -15
  129. package/docs-user/split-layout.md +136 -170
  130. package/docs-user/tabs.md +34 -0
  131. package/docs-user/titlebar.md +102 -0
  132. package/docs-user/toolbar.md +95 -22
  133. package/docs-user/twosplit-layout.md +254 -0
  134. package/docs-user/user-catalog.md +8 -1
  135. package/llms.txt +6 -1
  136. package/package.json +1 -2
  137. package/dist/button-Bn0BuLpO.js.map +0 -1
  138. package/dist/defaults-BCiDhZbF.js.map +0 -1
  139. package/dist/editable-label.d.ts.map +0 -1
  140. package/dist/icons-Bm2ByQ3s.js.map +0 -1
  141. package/dist/menu-DIfU70AA.js +0 -1609
  142. package/dist/menu-DIfU70AA.js.map +0 -1
  143. package/dist/slider-input-CT4gcF-o.js.map +0 -1
  144. package/dist/slider-input-XppH3vcy.d.ts.map +0 -1
  145. package/dist/split-layout.d.ts.map +0 -1
  146. package/dist/split-layout.js.map +0 -1
  147. package/dist/tab-list-D_1cYhB_.d.ts.map +0 -1
  148. package/dist/tickled-controller-BtevrRLV.d.ts.map +0 -1
  149. package/dist/tickled-controller-DkAU-0qL.js.map +0 -1
  150. package/dist/types-DlVNJez_.d.ts.map +0 -1
  151. package/dist/vertical-list.js.map +0 -1
  152. package/dist/xy-axis-B6yMjckW.js.map +0 -1
package/bundle/style.css CHANGED
@@ -23,7 +23,7 @@
23
23
  --font-mono: ui-monospace, monospace;
24
24
  --font-weight: 400;
25
25
  --font-weight-bold: 600;
26
- --text-xs: 10px;
26
+ --text-xs: 9px;
27
27
  --text-s: 11px;
28
28
  --text-m: 12px;
29
29
  --text-l: 13px;
package/dist/ac-text.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import { r as clearHighlights, t as applyHighlights } from "./highlight-B-eQrhhb.js";
2
- import { t as TickledController } from "./tickled-controller-DkAU-0qL.js";
2
+ import { t as TickledController } from "./tickled-controller-h9GmJ_bU.js";
3
3
  import { n as tickledStyles } from "./tickled-styles-BrAHEj1q.js";
4
- import { t as themeFallbacks } from "./fallbacks-DEE1nCTt.js";
4
+ import { t as themeFallbacks } from "./fallbacks-DNI9xt0F.js";
5
5
  import { t as popupSurfaceStyles } from "./popup-D80sj2QC.js";
6
6
  import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
7
+ import "./icon-CvnPanhA.js";
7
8
  import { LitElement, css, html, nothing } from "lit";
8
9
  import { property, state } from "lit/decorators.js";
9
10
  //#region src/ac-text/ac-text.ts
@@ -1 +1 @@
1
- {"version":3,"file":"ac-text.js","names":["#triggerQuery","#cancelPending","#debounceTimer","#scrollActiveIntoView","#selectItem","#commitText","#closePopup","#cache","#applyHighlights","#syncPopover","#abortController","#onItemPointerDown","#renderItem","#onInput","#onKeyDown","#onFocus","#onBlur","#renderPopup","customElement"],"sources":["../src/ac-text/ac-text.ts"],"sourcesContent":["import type { PropertyValues } from 'lit';\nimport type { HighlightTarget } from '../incr-search/types.js';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { applyHighlights, clearHighlights } from '../incr-search/highlight.js';\nimport { TickledController } from '../interaction/tickled-controller.js';\nimport { tickledStyles } from '../interaction/tickled-styles.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { popupSurfaceStyles } from '../styles/popup.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nconst HIGHLIGHT_KEY = `ac-text-highlight`;\n\n// ---- Public types ----\n\nexport type AcTextItem = {\n readonly label: string;\n readonly subLabel?: string;\n readonly icon?: string;\n readonly key?: string;\n readonly data?: unknown;\n /** When true, Tab-accept will not append `tabSuffix`. */\n readonly isLeaf?: boolean;\n /** Character positions within label that matched the query, used for CSS highlight rendering. */\n readonly positions?: ReadonlySet<number>;\n};\n\nexport type AcTextSelectDetail = {\n readonly item: AcTextItem;\n readonly query: string;\n};\n\nexport type AcTextSelectEvent = CustomEvent<AcTextSelectDetail>;\n\n/**\n * Fired when the user commits a value — either by pressing Enter on typed text\n * or by selecting an item from the autocomplete popup (keyboard or click).\n */\nexport type AcTextChangeDetail = {\n /** The committed text value (typed text, or the selected item's label). */\n readonly value: string;\n /**\n * The item key. For autocomplete items: `item.key ?? item.label`.\n * For plain typed text: the text itself.\n */\n readonly key: string;\n /** The item's `data` payload. Only present for autocomplete selections. */\n readonly data?: unknown;\n /** Whether the commit came from plain typed text or an autocomplete selection. */\n readonly source: `text` | `autocomplete`;\n};\n\nexport type AcTextChangeEvent = CustomEvent<AcTextChangeDetail>;\n\nexport type AcTextCompletionProvider\n = (query: string, signal: AbortSignal) => Promise<AcTextItem[]> | AcTextItem[];\n\n// ---- LRU cache ----\n\ntype LruCache<K, V> = {\n get: (key: K) => V | undefined;\n set: (key: K, value: V) => void;\n has: (key: K) => boolean;\n clear: () => void;\n};\n\nfunction makeLruCache<K, V>(maxSize: number): LruCache<K, V> {\n const map = new Map<K, V>();\n return {\n get: (key: K) => map.get(key),\n set: (key: K, value: V) => {\n if (map.has(key))\n map.delete(key);\n map.set(key, value);\n if (map.size > maxSize)\n map.delete(map.keys().next().value!);\n },\n has: (key: K) => map.has(key),\n clear: () => map.clear(),\n };\n}\n\n// ---- Component ----\n\n/**\n * VS Code command-palette style autocomplete text input.\n *\n * Set `completionProvider` to a function that returns matching items for a\n * given query string. Results are shown in a popup that only exists in the\n * DOM while the input has focus.\n *\n * @fires {AcTextSelectEvent} ac-select — when an autocomplete item is selected\n * @fires {AcTextChangeEvent} change — when the user commits a value (Enter on typed text or autocomplete selection)\n *\n * @example\n * ```html\n * <ixfx-ac-text placeholder=\"Search commands…\"></ixfx-ac-text>\n * ```\n * ```ts\n * el.completionProvider = async (query) => commands.filter(c =>\n * c.label.toLowerCase().includes(query.toLowerCase())\n * );\n * el.addEventListener('change', e => console.log(e.detail));\n * ```\n */\n@customElement(`ixfx-ac-text`)\nexport class AcTextElement extends LitElement {\n private static _count = 0;\n private readonly _anchorName = `--ac-text-anchor-${AcTextElement._count++}`;\n\n /** Provides completion results for a query string. */\n @property({ type: Object })\n completionProvider: AcTextCompletionProvider | undefined;\n\n /** Placeholder text for the input. */\n @property({ type: String })\n placeholder = ``;\n\n /** Maximum number of query results to cache (LRU). */\n @property({ type: Number, attribute: `cache-size` })\n cacheSize = 20;\n\n /** Debounce delay in ms before invoking the provider after keystroke. */\n @property({ type: Number, attribute: `debounce-ms` })\n debounceMs = 150;\n\n /**\n * Pre-populate the input with this value. Updated externally after construction is ignored\n * unless the input is not currently focused.\n */\n @property({ type: String })\n value = ``;\n\n /**\n * String appended to the label when Tab is used to accept a suggestion.\n * Useful for path-style inputs where Tab-accepting a segment should add the separator.\n */\n @property({ type: String, attribute: `tab-suffix` })\n tabSuffix = ``;\n\n @state() private _query = ``;\n @state() private _results: AcTextItem[] = [];\n @state() private _isOpen = false;\n @state() private _isLoading = false;\n\n private tickled = new TickledController<number>(this, {\n getItems: () => this._results.map((_, i) => ({ id: i, enabled: true })),\n });\n\n #cache: LruCache<string, AcTextItem[]> = makeLruCache(20);\n #debounceTimer: ReturnType<typeof setTimeout> | undefined;\n #abortController: AbortController | undefined;\n\n constructor() {\n super();\n this.#cache = makeLruCache(this.cacheSize);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#cancelPending();\n clearHighlights({ key: HIGHLIGHT_KEY });\n }\n\n override firstUpdated(): void {\n this.style.setProperty(`--anchor-name`, this._anchorName);\n }\n\n protected override updated(changedProps: PropertyValues): void {\n if (changedProps.has(`completionProvider`)) {\n this.#cache.clear();\n }\n if (changedProps.has(`cacheSize`)) {\n this.#cache = makeLruCache(this.cacheSize);\n }\n if (changedProps.has(`value`)) {\n // Only sync when the input isn't focused (avoid clobbering user typing)\n const input = this.shadowRoot?.querySelector(`input`);\n if (!input || document.activeElement !== input) {\n this._query = this.value;\n }\n }\n this.#applyHighlights();\n this.#syncPopover();\n }\n\n /** Keep the native popover in sync with `_isOpen` (popup is lazily rendered). */\n #syncPopover(): void {\n if (!this.shadowRoot)\n return;\n const popup = this.shadowRoot.querySelector<HTMLElement>(`.popup`);\n if (!popup)\n return;\n try {\n if (this._isOpen) {\n if (!popup.matches(`:popover-open`))\n popup.showPopover();\n } else if (popup.matches(`:popover-open`)) {\n popup.hidePopover();\n }\n } catch {\n // Popover API not supported\n }\n }\n\n #applyHighlights(): void {\n if (!this._isOpen || !this.shadowRoot) {\n clearHighlights({ key: HIGHLIGHT_KEY });\n return;\n }\n const labelEls = this.shadowRoot.querySelectorAll(`.item-label`);\n const targets: HighlightTarget[] = [];\n labelEls.forEach((el, index) => {\n const positions = this._results[index]?.positions;\n if (!positions?.size)\n return;\n targets.push({ element: el, text: this._results[index].label, positions });\n });\n applyHighlights(targets, { key: HIGHLIGHT_KEY });\n }\n\n override focus(options?: FocusOptions, selectionStart?: number, selectionEnd?: number): void {\n const input = this.shadowRoot?.querySelector(`input`) as HTMLInputElement | null;\n if (!input)\n return;\n input.focus(options);\n const start = selectionStart ?? input.value.length;\n const end = selectionEnd ?? input.value.length;\n input.setSelectionRange(start, end);\n input.scrollLeft = input.scrollWidth;\n }\n\n focusWithValue(value: string, selectionStart?: number, selectionEnd?: number): void {\n this._query = value;\n this.updateComplete.then(() => {\n const input = this.shadowRoot?.querySelector(`input`) as HTMLInputElement | null;\n if (!input)\n return;\n input.focus();\n const start = selectionStart ?? input.value.length;\n const end = selectionEnd ?? input.value.length;\n input.setSelectionRange(start, end);\n });\n }\n\n selectRange(start: number, end?: number): void {\n const input = this.shadowRoot?.querySelector(`input`) as HTMLInputElement | null;\n if (!input)\n return;\n const endPos = end ?? input.value.length;\n input.setSelectionRange(start, endPos);\n }\n\n // ---- Handlers ----\n\n #onFocus = (): void => {\n this._isOpen = true;\n if (this._query.trim()) {\n this.#triggerQuery(this._query);\n }\n };\n\n #onBlur = (): void => {\n this.#cancelPending();\n this._isOpen = false;\n this.tickled.clearTickled();\n };\n\n #onInput = (e: Event): void => {\n const input = e.target as HTMLInputElement;\n this._query = input.value;\n\n if (this.#debounceTimer !== undefined) {\n clearTimeout(this.#debounceTimer);\n }\n\n if (!this._query.trim()) {\n this._results = [];\n this.tickled.clearTickled();\n this._isLoading = false;\n this._isOpen = false;\n return;\n }\n\n this._isOpen = true;\n this.#debounceTimer = setTimeout(() => {\n this.#triggerQuery(this._query);\n }, this.debounceMs);\n };\n\n #onKeyDown = (e: KeyboardEvent): void => {\n switch (e.key) {\n case `ArrowDown`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n if (this._results.length === 0)\n return;\n this.tickled.handleKeyboardNavigation(`next`);\n this.#scrollActiveIntoView();\n break;\n }\n case `ArrowUp`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n if (this._results.length === 0)\n return;\n this.tickled.handleKeyboardNavigation(`previous`);\n this.#scrollActiveIntoView();\n break;\n }\n case `Enter`: {\n const tickledIndex = this.tickled.tickledId ?? -1;\n if (this._isOpen && tickledIndex >= 0 && this._results[tickledIndex]) {\n // Autocomplete selection via keyboard\n e.preventDefault();\n this.#selectItem(this._results[tickledIndex]);\n } else if (this._query.trim()) {\n // Plain text commit\n e.preventDefault();\n this.#commitText(this._query);\n }\n break;\n }\n case `Tab`: {\n const tickledIndex = this.tickled.tickledId ?? -1;\n if (this._isOpen && tickledIndex >= 0 && this._results[tickledIndex]) {\n e.preventDefault();\n const tabItem = this._results[tickledIndex];\n this._query = tabItem.label + (tabItem.isLeaf ? `` : this.tabSuffix);\n this.tickled.clearTickled();\n this.#triggerQuery(this._query);\n }\n break;\n }\n case `Escape`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n this.#closePopup();\n break;\n }\n }\n };\n\n /** pointerdown beats blur — prevents popup vanishing before click registers */\n #onItemPointerDown = (e: PointerEvent, item: AcTextItem): void => {\n e.preventDefault();\n this.#selectItem(item);\n };\n\n // ---- Internal logic ----\n\n #triggerQuery(query: string): void {\n if (!this.completionProvider)\n return;\n\n const cached = this.#cache.get(query);\n if (cached !== undefined) {\n this._results = cached;\n this.tickled.clearTickled();\n this._isLoading = false;\n return;\n }\n\n // Cancel any in-flight request\n this.#abortController?.abort();\n this.#abortController = new AbortController();\n const { signal } = this.#abortController;\n\n this._isLoading = true;\n\n Promise.resolve(this.completionProvider(query, signal))\n .then((results) => {\n if (signal.aborted)\n return;\n this.#cache.set(query, results);\n this._results = results;\n this.tickled.clearTickled();\n this._isLoading = false;\n })\n .catch((err) => {\n if (signal.aborted)\n return;\n console.error(`[ixfx-ac-text] completionProvider error:`, err);\n this._results = [];\n this._isLoading = false;\n });\n }\n\n #selectItem(item: AcTextItem): void {\n this.dispatchEvent(new CustomEvent<AcTextSelectDetail>(`ac-select`, {\n detail: { item, query: this._query },\n bubbles: true,\n composed: true,\n }));\n this.dispatchEvent(new CustomEvent<AcTextChangeDetail>(`change`, {\n detail: {\n value: item.label,\n key: item.key ?? item.label,\n data: item.data,\n source: `autocomplete`,\n },\n bubbles: true,\n composed: true,\n }));\n this._query = item.label;\n this._isOpen = false;\n this.tickled.clearTickled();\n }\n\n #commitText(text: string): void {\n this.dispatchEvent(new CustomEvent<AcTextChangeDetail>(`change`, {\n detail: {\n value: text,\n key: text,\n source: `text`,\n },\n bubbles: true,\n composed: true,\n }));\n this._isOpen = false;\n this.tickled.clearTickled();\n }\n\n #closePopup(): void {\n this._isOpen = false;\n this.tickled.clearTickled();\n clearHighlights({ key: HIGHLIGHT_KEY });\n }\n\n #cancelPending(): void {\n if (this.#debounceTimer !== undefined) {\n clearTimeout(this.#debounceTimer);\n this.#debounceTimer = undefined;\n }\n this.#abortController?.abort();\n this.#abortController = undefined;\n this._isLoading = false;\n }\n\n #scrollActiveIntoView(): void {\n // After Lit renders the new tickled item, scroll it into view\n this.updateComplete.then(() => {\n const item = this.shadowRoot?.querySelector(`.item.tickled`);\n item?.scrollIntoView({ block: `nearest` });\n });\n }\n\n // ---- Render helpers ----\n\n #renderItem(item: AcTextItem, index: number) {\n const isTickled = this.tickled.isTickled(index);\n return html`\n <div\n class=\"item ${isTickled ? `tickled` : ``}\"\n role=\"option\"\n id=\"ac-item-${index}\"\n aria-selected=${isTickled}\n @pointerenter=${() => this.tickled.handlePointerEnter(index)}\n @pointerdown=${(e: PointerEvent) => this.#onItemPointerDown(e, item)}\n >\n ${item.icon ? html`<ixfx-icon class=\"item-icon\" name=${item.icon}></ixfx-icon>` : nothing}\n <span class=\"item-label\">${item.label}</span>\n ${item.subLabel ? html`<span class=\"item-sublabel\">${item.subLabel}</span>` : nothing}\n </div>\n `;\n }\n\n #renderPopup() {\n const showEmpty = !this._isLoading && this._results.length === 0;\n return html`\n <div\n class=\"popup popup-surface\"\n popover=\"manual\"\n role=\"listbox\"\n aria-label=\"Suggestions\"\n data-input-mode=${this.tickled.inputMode}\n @pointerleave=${(e: PointerEvent) => this.tickled.handlePointerLeave(e)}\n >\n ${showEmpty\n ? html`<div class=\"no-results\">No matching results</div>`\n : this._results.map((item, i) => this.#renderItem(item, i))\n }\n </div>\n `;\n }\n\n protected override render() {\n const tickledIndex = this.tickled.tickledId ?? -1;\n const activeDescendant = tickledIndex >= 0 ? `ac-item-${tickledIndex}` : undefined;\n return html`\n <div class=\"input-wrapper\">\n <input\n type=\"text\"\n .value=${this._query}\n placeholder=${this.placeholder || nothing}\n autocomplete=\"off\"\n spellcheck=\"false\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=${this._isOpen}\n aria-activedescendant=${activeDescendant ?? nothing}\n @input=${this.#onInput}\n @keydown=${this.#onKeyDown}\n @focus=${this.#onFocus}\n @blur=${this.#onBlur}\n >\n ${this._isLoading\n ? html`<span class=\"spinner\" aria-hidden=\"true\"></span>`\n : nothing\n }\n </div>\n ${this._isOpen ? this.#renderPopup() : nothing}\n `;\n }\n\n static override styles = [\n themeFallbacks,\n tickledStyles,\n popupSurfaceStyles,\n css`\n :host {\n display: block;\n position: relative;\n font-family: var(--font-family, system-ui, sans-serif);\n font-size: var(--text-m, 12px);\n color: var(--surface-2-text);\n }\n\n /* ---- Input ---- */\n\n .input-wrapper {\n display: flex;\n align-items: center;\n position: relative;\n anchor-name: var(--anchor-name);\n }\n\n input {\n appearance: none;\n width: 100%;\n box-sizing: border-box;\n padding: var(--ac-input-padding, var(--space-m, 8px) var(--space-l, 12px));\n background: var(--ac-input-background, var(--surface-3, var(--surface-2)));\n color: var(--surface-2-text);\n border: var(--ac-input-border, var(--border));\n border-radius: var(--ac-input-border-radius, var(--radius-m, 4px));\n font: inherit;\n caret-color: var(--accent);\n outline: none;\n transition: border-color var(--transition, 0.15s ease-out);\n }\n\n input:focus {\n border-color: var(--accent);\n }\n\n input::placeholder {\n color: var(--surface-muted-text);\n }\n\n /* ---- Spinner ---- */\n\n .spinner {\n position: absolute;\n right: var(--space-m, 8px);\n width: 12px;\n height: 12px;\n border: 2px solid var(--surface-5);\n border-top-color: var(--accent);\n border-radius: 50%;\n animation: ac-spin 0.7s linear infinite;\n flex-shrink: 0;\n pointer-events: none;\n }\n\n @keyframes ac-spin {\n to { transform: rotate(360deg); }\n }\n\n /* ---- Popup ---- */\n\n .popup {\n position: fixed;\n inset: unset;\n margin: 0;\n width: anchor-size(width);\n position-anchor: var(--anchor-name);\n position-area: block-end span-inline-start;\n margin-block-start: 2px;\n position-try-fallbacks: flip-block;\n z-index: 100;\n background: var(--surface-3, var(--surface-2));\n border: var(--border);\n border-radius: var(--radius-m, 4px);\n box-shadow: var(--shadow-l, 0 4px 24px rgba(0, 0, 0, 0.5));\n padding: var(--space-xs, 3px) 0;\n max-height: 280px;\n overflow-y: auto;\n font-size: var(--ac-popup-font-size, var(--text-s, 11px));\n }\n\n /* ---- Items ---- */\n\n .item {\n display: flex;\n align-items: center;\n gap: var(--space-m, 8px);\n padding: var(--space-xs, 3px) var(--space-l, 12px);\n cursor: pointer;\n border-radius: var(--radius-s, 3px);\n margin: 0 var(--space-xs, 3px);\n transition: background var(--transition, 0.1s ease-out);\n user-select: none;\n white-space: nowrap;\n min-height: 28px;\n }\n\n \n\n .item.tickled {\n background: var(--_item-focused-bg, var(--accent));\n color: var(--accent-text, #fff);\n }\n\n .item.tickled .item-sublabel {\n color: color-mix(in srgb, var(--accent-text, #fff) 70%, transparent);\n }\n\n .item-icon {\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n }\n\n .item-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .item-sublabel {\n flex-shrink: 0;\n margin-left: auto;\n color: var(--surface-muted-text);\n font-size: var(--text-s, 11px);\n }\n\n ::highlight(ac-text-highlight) {\n background: var(--ac-highlight-background, var(--accent));\n color: var(--ac-highlight-color, var(--accent-text, #fff));\n border-radius: 2px;\n padding: 0 1px;\n }\n\n /* ---- Empty state ---- */\n\n .no-results {\n padding: var(--space-m, 8px) var(--space-l, 12px);\n color: var(--surface-muted-text);\n font-style: italic;\n font-size: var(--text-s, 11px);\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-ac-text': AcTextElement;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ac-text.js","names":["#triggerQuery","#cancelPending","#debounceTimer","#scrollActiveIntoView","#selectItem","#commitText","#closePopup","#cache","#applyHighlights","#syncPopover","#abortController","#onItemPointerDown","#renderItem","#onInput","#onKeyDown","#onFocus","#onBlur","#renderPopup","customElement"],"sources":["../src/ac-text/ac-text.ts"],"sourcesContent":["import type { PropertyValues } from 'lit';\nimport type { HighlightTarget } from '../incr-search/types.js';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { applyHighlights, clearHighlights } from '../incr-search/highlight.js';\nimport { TickledController } from '../interaction/tickled-controller.js';\nimport { tickledStyles } from '../interaction/tickled-styles.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { popupSurfaceStyles } from '../styles/popup.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nconst HIGHLIGHT_KEY = `ac-text-highlight`;\n\n// ---- Public types ----\n\nexport type AcTextItem = {\n readonly label: string;\n readonly subLabel?: string;\n readonly icon?: string;\n readonly key?: string;\n readonly data?: unknown;\n /** When true, Tab-accept will not append `tabSuffix`. */\n readonly isLeaf?: boolean;\n /** Character positions within label that matched the query, used for CSS highlight rendering. */\n readonly positions?: ReadonlySet<number>;\n};\n\nexport type AcTextSelectDetail = {\n readonly item: AcTextItem;\n readonly query: string;\n};\n\nexport type AcTextSelectEvent = CustomEvent<AcTextSelectDetail>;\n\n/**\n * Fired when the user commits a value — either by pressing Enter on typed text\n * or by selecting an item from the autocomplete popup (keyboard or click).\n */\nexport type AcTextChangeDetail = {\n /** The committed text value (typed text, or the selected item's label). */\n readonly value: string;\n /**\n * The item key. For autocomplete items: `item.key ?? item.label`.\n * For plain typed text: the text itself.\n */\n readonly key: string;\n /** The item's `data` payload. Only present for autocomplete selections. */\n readonly data?: unknown;\n /** Whether the commit came from plain typed text or an autocomplete selection. */\n readonly source: `text` | `autocomplete`;\n};\n\nexport type AcTextChangeEvent = CustomEvent<AcTextChangeDetail>;\n\nexport type AcTextCompletionProvider\n = (query: string, signal: AbortSignal) => Promise<AcTextItem[]> | AcTextItem[];\n\n// ---- LRU cache ----\n\ntype LruCache<K, V> = {\n get: (key: K) => V | undefined;\n set: (key: K, value: V) => void;\n has: (key: K) => boolean;\n clear: () => void;\n};\n\nfunction makeLruCache<K, V>(maxSize: number): LruCache<K, V> {\n const map = new Map<K, V>();\n return {\n get: (key: K) => map.get(key),\n set: (key: K, value: V) => {\n if (map.has(key))\n map.delete(key);\n map.set(key, value);\n if (map.size > maxSize)\n map.delete(map.keys().next().value!);\n },\n has: (key: K) => map.has(key),\n clear: () => map.clear(),\n };\n}\n\n// ---- Component ----\n\n/**\n * VS Code command-palette style autocomplete text input.\n *\n * Set `completionProvider` to a function that returns matching items for a\n * given query string. Results are shown in a popup that only exists in the\n * DOM while the input has focus.\n *\n * @fires {AcTextSelectEvent} ac-select — when an autocomplete item is selected\n * @fires {AcTextChangeEvent} change — when the user commits a value (Enter on typed text or autocomplete selection)\n *\n * @example\n * ```html\n * <ixfx-ac-text placeholder=\"Search commands…\"></ixfx-ac-text>\n * ```\n * ```ts\n * el.completionProvider = async (query) => commands.filter(c =>\n * c.label.toLowerCase().includes(query.toLowerCase())\n * );\n * el.addEventListener('change', e => console.log(e.detail));\n * ```\n */\n@customElement(`ixfx-ac-text`)\nexport class AcTextElement extends LitElement {\n private static _count = 0;\n private readonly _anchorName = `--ac-text-anchor-${AcTextElement._count++}`;\n\n /** Provides completion results for a query string. */\n @property({ type: Object })\n completionProvider: AcTextCompletionProvider | undefined;\n\n /** Placeholder text for the input. */\n @property({ type: String })\n placeholder = ``;\n\n /** Maximum number of query results to cache (LRU). */\n @property({ type: Number, attribute: `cache-size` })\n cacheSize = 20;\n\n /** Debounce delay in ms before invoking the provider after keystroke. */\n @property({ type: Number, attribute: `debounce-ms` })\n debounceMs = 150;\n\n /**\n * Pre-populate the input with this value. Updated externally after construction is ignored\n * unless the input is not currently focused.\n */\n @property({ type: String })\n value = ``;\n\n /**\n * String appended to the label when Tab is used to accept a suggestion.\n * Useful for path-style inputs where Tab-accepting a segment should add the separator.\n */\n @property({ type: String, attribute: `tab-suffix` })\n tabSuffix = ``;\n\n @state() private _query = ``;\n @state() private _results: AcTextItem[] = [];\n @state() private _isOpen = false;\n @state() private _isLoading = false;\n\n private tickled = new TickledController<number>(this, {\n getItems: () => this._results.map((_, i) => ({ id: i, enabled: true })),\n });\n\n #cache: LruCache<string, AcTextItem[]> = makeLruCache(20);\n #debounceTimer: ReturnType<typeof setTimeout> | undefined;\n #abortController: AbortController | undefined;\n\n constructor() {\n super();\n this.#cache = makeLruCache(this.cacheSize);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.#cancelPending();\n clearHighlights({ key: HIGHLIGHT_KEY });\n }\n\n override firstUpdated(): void {\n this.style.setProperty(`--anchor-name`, this._anchorName);\n }\n\n protected override updated(changedProps: PropertyValues): void {\n if (changedProps.has(`completionProvider`)) {\n this.#cache.clear();\n }\n if (changedProps.has(`cacheSize`)) {\n this.#cache = makeLruCache(this.cacheSize);\n }\n if (changedProps.has(`value`)) {\n // Only sync when the input isn't focused (avoid clobbering user typing)\n const input = this.shadowRoot?.querySelector(`input`);\n if (!input || document.activeElement !== input) {\n this._query = this.value;\n }\n }\n this.#applyHighlights();\n this.#syncPopover();\n }\n\n /** Keep the native popover in sync with `_isOpen` (popup is lazily rendered). */\n #syncPopover(): void {\n if (!this.shadowRoot)\n return;\n const popup = this.shadowRoot.querySelector<HTMLElement>(`.popup`);\n if (!popup)\n return;\n try {\n if (this._isOpen) {\n if (!popup.matches(`:popover-open`))\n popup.showPopover();\n } else if (popup.matches(`:popover-open`)) {\n popup.hidePopover();\n }\n } catch {\n // Popover API not supported\n }\n }\n\n #applyHighlights(): void {\n if (!this._isOpen || !this.shadowRoot) {\n clearHighlights({ key: HIGHLIGHT_KEY });\n return;\n }\n const labelEls = this.shadowRoot.querySelectorAll(`.item-label`);\n const targets: HighlightTarget[] = [];\n labelEls.forEach((el, index) => {\n const positions = this._results[index]?.positions;\n if (!positions?.size)\n return;\n targets.push({ element: el, text: this._results[index].label, positions });\n });\n applyHighlights(targets, { key: HIGHLIGHT_KEY });\n }\n\n override focus(options?: FocusOptions, selectionStart?: number, selectionEnd?: number): void {\n const input = this.shadowRoot?.querySelector(`input`) as HTMLInputElement | null;\n if (!input)\n return;\n input.focus(options);\n const start = selectionStart ?? input.value.length;\n const end = selectionEnd ?? input.value.length;\n input.setSelectionRange(start, end);\n input.scrollLeft = input.scrollWidth;\n }\n\n focusWithValue(value: string, selectionStart?: number, selectionEnd?: number): void {\n this._query = value;\n this.updateComplete.then(() => {\n const input = this.shadowRoot?.querySelector(`input`) as HTMLInputElement | null;\n if (!input)\n return;\n input.focus();\n const start = selectionStart ?? input.value.length;\n const end = selectionEnd ?? input.value.length;\n input.setSelectionRange(start, end);\n });\n }\n\n selectRange(start: number, end?: number): void {\n const input = this.shadowRoot?.querySelector(`input`) as HTMLInputElement | null;\n if (!input)\n return;\n const endPos = end ?? input.value.length;\n input.setSelectionRange(start, endPos);\n }\n\n // ---- Handlers ----\n\n #onFocus = (): void => {\n this._isOpen = true;\n if (this._query.trim()) {\n this.#triggerQuery(this._query);\n }\n };\n\n #onBlur = (): void => {\n this.#cancelPending();\n this._isOpen = false;\n this.tickled.clearTickled();\n };\n\n #onInput = (e: Event): void => {\n const input = e.target as HTMLInputElement;\n this._query = input.value;\n\n if (this.#debounceTimer !== undefined) {\n clearTimeout(this.#debounceTimer);\n }\n\n if (!this._query.trim()) {\n this._results = [];\n this.tickled.clearTickled();\n this._isLoading = false;\n this._isOpen = false;\n return;\n }\n\n this._isOpen = true;\n this.#debounceTimer = setTimeout(() => {\n this.#triggerQuery(this._query);\n }, this.debounceMs);\n };\n\n #onKeyDown = (e: KeyboardEvent): void => {\n switch (e.key) {\n case `ArrowDown`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n if (this._results.length === 0)\n return;\n this.tickled.handleKeyboardNavigation(`next`);\n this.#scrollActiveIntoView();\n break;\n }\n case `ArrowUp`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n if (this._results.length === 0)\n return;\n this.tickled.handleKeyboardNavigation(`previous`);\n this.#scrollActiveIntoView();\n break;\n }\n case `Enter`: {\n const tickledIndex = this.tickled.tickledId ?? -1;\n if (this._isOpen && tickledIndex >= 0 && this._results[tickledIndex]) {\n // Autocomplete selection via keyboard\n e.preventDefault();\n this.#selectItem(this._results[tickledIndex]);\n } else if (this._query.trim()) {\n // Plain text commit\n e.preventDefault();\n this.#commitText(this._query);\n }\n break;\n }\n case `Tab`: {\n const tickledIndex = this.tickled.tickledId ?? -1;\n if (this._isOpen && tickledIndex >= 0 && this._results[tickledIndex]) {\n e.preventDefault();\n const tabItem = this._results[tickledIndex];\n this._query = tabItem.label + (tabItem.isLeaf ? `` : this.tabSuffix);\n this.tickled.clearTickled();\n this.#triggerQuery(this._query);\n }\n break;\n }\n case `Escape`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n this.#closePopup();\n break;\n }\n }\n };\n\n /** pointerdown beats blur — prevents popup vanishing before click registers */\n #onItemPointerDown = (e: PointerEvent, item: AcTextItem): void => {\n e.preventDefault();\n this.#selectItem(item);\n };\n\n // ---- Internal logic ----\n\n #triggerQuery(query: string): void {\n if (!this.completionProvider)\n return;\n\n const cached = this.#cache.get(query);\n if (cached !== undefined) {\n this._results = cached;\n this.tickled.clearTickled();\n this._isLoading = false;\n return;\n }\n\n // Cancel any in-flight request\n this.#abortController?.abort();\n this.#abortController = new AbortController();\n const { signal } = this.#abortController;\n\n this._isLoading = true;\n\n Promise.resolve(this.completionProvider(query, signal))\n .then((results) => {\n if (signal.aborted)\n return;\n this.#cache.set(query, results);\n this._results = results;\n this.tickled.clearTickled();\n this._isLoading = false;\n })\n .catch((err) => {\n if (signal.aborted)\n return;\n console.error(`[ixfx-ac-text] completionProvider error:`, err);\n this._results = [];\n this._isLoading = false;\n });\n }\n\n #selectItem(item: AcTextItem): void {\n this.dispatchEvent(new CustomEvent<AcTextSelectDetail>(`ac-select`, {\n detail: { item, query: this._query },\n bubbles: true,\n composed: true,\n }));\n this.dispatchEvent(new CustomEvent<AcTextChangeDetail>(`change`, {\n detail: {\n value: item.label,\n key: item.key ?? item.label,\n data: item.data,\n source: `autocomplete`,\n },\n bubbles: true,\n composed: true,\n }));\n this._query = item.label;\n this._isOpen = false;\n this.tickled.clearTickled();\n }\n\n #commitText(text: string): void {\n this.dispatchEvent(new CustomEvent<AcTextChangeDetail>(`change`, {\n detail: {\n value: text,\n key: text,\n source: `text`,\n },\n bubbles: true,\n composed: true,\n }));\n this._isOpen = false;\n this.tickled.clearTickled();\n }\n\n #closePopup(): void {\n this._isOpen = false;\n this.tickled.clearTickled();\n clearHighlights({ key: HIGHLIGHT_KEY });\n }\n\n #cancelPending(): void {\n if (this.#debounceTimer !== undefined) {\n clearTimeout(this.#debounceTimer);\n this.#debounceTimer = undefined;\n }\n this.#abortController?.abort();\n this.#abortController = undefined;\n this._isLoading = false;\n }\n\n #scrollActiveIntoView(): void {\n // After Lit renders the new tickled item, scroll it into view\n this.updateComplete.then(() => {\n const item = this.shadowRoot?.querySelector(`.item.tickled`);\n item?.scrollIntoView({ block: `nearest` });\n });\n }\n\n // ---- Render helpers ----\n\n #renderItem(item: AcTextItem, index: number) {\n const isTickled = this.tickled.isTickled(index);\n return html`\n <div\n class=\"item ${isTickled ? `tickled` : ``}\"\n role=\"option\"\n id=\"ac-item-${index}\"\n aria-selected=${isTickled}\n @pointerenter=${() => this.tickled.handlePointerEnter(index)}\n @pointerdown=${(e: PointerEvent) => this.#onItemPointerDown(e, item)}\n >\n ${item.icon ? html`<ixfx-icon class=\"item-icon\" name=${item.icon}></ixfx-icon>` : nothing}\n <span class=\"item-label\">${item.label}</span>\n ${item.subLabel ? html`<span class=\"item-sublabel\">${item.subLabel}</span>` : nothing}\n </div>\n `;\n }\n\n #renderPopup() {\n const showEmpty = !this._isLoading && this._results.length === 0;\n return html`\n <div\n class=\"popup popup-surface\"\n popover=\"manual\"\n role=\"listbox\"\n aria-label=\"Suggestions\"\n data-input-mode=${this.tickled.inputMode}\n @pointerleave=${(e: PointerEvent) => this.tickled.handlePointerLeave(e)}\n >\n ${showEmpty\n ? html`<div class=\"no-results\">No matching results</div>`\n : this._results.map((item, i) => this.#renderItem(item, i))\n }\n </div>\n `;\n }\n\n protected override render() {\n const tickledIndex = this.tickled.tickledId ?? -1;\n const activeDescendant = tickledIndex >= 0 ? `ac-item-${tickledIndex}` : undefined;\n return html`\n <div class=\"input-wrapper\">\n <input\n type=\"text\"\n .value=${this._query}\n placeholder=${this.placeholder || nothing}\n autocomplete=\"off\"\n spellcheck=\"false\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=${this._isOpen}\n aria-activedescendant=${activeDescendant ?? nothing}\n @input=${this.#onInput}\n @keydown=${this.#onKeyDown}\n @focus=${this.#onFocus}\n @blur=${this.#onBlur}\n >\n ${this._isLoading\n ? html`<span class=\"spinner\" aria-hidden=\"true\"></span>`\n : nothing\n }\n </div>\n ${this._isOpen ? this.#renderPopup() : nothing}\n `;\n }\n\n static override styles = [\n themeFallbacks,\n tickledStyles,\n popupSurfaceStyles,\n css`\n :host {\n display: block;\n position: relative;\n font-family: var(--font-family, system-ui, sans-serif);\n font-size: var(--text-m, 12px);\n color: var(--surface-2-text);\n }\n\n /* ---- Input ---- */\n\n .input-wrapper {\n display: flex;\n align-items: center;\n position: relative;\n anchor-name: var(--anchor-name);\n }\n\n input {\n appearance: none;\n width: 100%;\n box-sizing: border-box;\n padding: var(--ac-input-padding, var(--space-m, 8px) var(--space-l, 12px));\n background: var(--ac-input-background, var(--surface-3, var(--surface-2)));\n color: var(--surface-2-text);\n border: var(--ac-input-border, var(--border));\n border-radius: var(--ac-input-border-radius, var(--radius-m, 4px));\n font: inherit;\n caret-color: var(--accent);\n outline: none;\n transition: border-color var(--transition, 0.15s ease-out);\n }\n\n input:focus {\n border-color: var(--accent);\n }\n\n input::placeholder {\n color: var(--surface-muted-text);\n }\n\n /* ---- Spinner ---- */\n\n .spinner {\n position: absolute;\n right: var(--space-m, 8px);\n width: 12px;\n height: 12px;\n border: 2px solid var(--surface-5);\n border-top-color: var(--accent);\n border-radius: 50%;\n animation: ac-spin 0.7s linear infinite;\n flex-shrink: 0;\n pointer-events: none;\n }\n\n @keyframes ac-spin {\n to { transform: rotate(360deg); }\n }\n\n /* ---- Popup ---- */\n\n .popup {\n position: fixed;\n inset: unset;\n margin: 0;\n width: anchor-size(width);\n position-anchor: var(--anchor-name);\n position-area: block-end span-inline-start;\n margin-block-start: 2px;\n position-try-fallbacks: flip-block;\n z-index: 100;\n background: var(--surface-3, var(--surface-2));\n border: var(--border);\n border-radius: var(--radius-m, 4px);\n box-shadow: var(--shadow-l, 0 4px 24px rgba(0, 0, 0, 0.5));\n padding: var(--space-xs, 3px) 0;\n max-height: 280px;\n overflow-y: auto;\n font-size: var(--ac-popup-font-size, var(--text-s, 11px));\n }\n\n /* ---- Items ---- */\n\n .item {\n display: flex;\n align-items: center;\n gap: var(--space-m, 8px);\n padding: var(--space-xs, 3px) var(--space-l, 12px);\n cursor: pointer;\n border-radius: var(--radius-s, 3px);\n margin: 0 var(--space-xs, 3px);\n transition: background var(--transition, 0.1s ease-out);\n user-select: none;\n white-space: nowrap;\n min-height: 28px;\n }\n\n \n\n .item.tickled {\n background: var(--_item-focused-bg, var(--accent));\n color: var(--accent-text, #fff);\n }\n\n .item.tickled .item-sublabel {\n color: color-mix(in srgb, var(--accent-text, #fff) 70%, transparent);\n }\n\n .item-icon {\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n }\n\n .item-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .item-sublabel {\n flex-shrink: 0;\n margin-left: auto;\n color: var(--surface-muted-text);\n font-size: var(--text-s, 11px);\n }\n\n ::highlight(ac-text-highlight) {\n background: var(--ac-highlight-background, var(--accent));\n color: var(--ac-highlight-color, var(--accent-text, #fff));\n border-radius: 2px;\n padding: 0 1px;\n }\n\n /* ---- Empty state ---- */\n\n .no-results {\n padding: var(--space-m, 8px) var(--space-l, 12px);\n color: var(--surface-muted-text);\n font-style: italic;\n font-size: var(--text-s, 11px);\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-ac-text': AcTextElement;\n }\n}\n"],"mappings":"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"}
package/dist/ac-token.js CHANGED
@@ -1,7 +1,8 @@
1
- import { t as TickledController } from "./tickled-controller-DkAU-0qL.js";
1
+ import { t as TickledController } from "./tickled-controller-h9GmJ_bU.js";
2
2
  import { n as tickledStyles, t as tickledItemStyles } from "./tickled-styles-BrAHEj1q.js";
3
- import { t as themeFallbacks } from "./fallbacks-DEE1nCTt.js";
3
+ import { t as themeFallbacks } from "./fallbacks-DNI9xt0F.js";
4
4
  import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
5
+ import "./icon-CvnPanhA.js";
5
6
  import { t as DataController } from "./data-controller-DOlmqNKb.js";
6
7
  import { n as createAcCompletionProvider } from "./incr-search-vCzuao-2.js";
7
8
  import { LitElement, css, html, nothing } from "lit";
@@ -1 +1 @@
1
- {"version":3,"file":"ac-token.js","names":["#data","#scheduleSuggestionFetch","#addToken","#startEditingSelectedToken","#handleNavigationKey","#selectSuggestion","#removeToken","#cache","#emitChange","#buildStaticProvider","#debounceTimer","#lastSuggestions","#staticProvider","#closePopup","#scrollSuggestionIntoView","#buildCachedProvider","#filterUsed","#onChipPointerDown","#onSuggestionPointerDown","#renderSuggestion","#onWrapperClick","#renderChip","#onInput","#onKeyDown","#onFocus","#onBlur","#onPaste","#renderPopup","customElement"],"sources":["../src/ac-token/ac-token.ts"],"sourcesContent":["/* eslint-disable ts/no-unsafe-declaration-merging */\nimport type { PropertyValues } from 'lit';\nimport type { IDataProvider } from '../common/data-provider.js';\nimport type {\n AcTokenAddDetail,\n AcTokenElementEventMap,\n AcTokenItem,\n AcTokenizerFn,\n AcTokenRemoveDetail,\n AcTokensChangeDetail,\n} from './types.js';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { DataController } from '../common/data-controller.js';\nimport { createAcCompletionProvider } from '../incr-search/index.js';\nimport { TickledController } from '../interaction/tickled-controller.js';\nimport { tickledItemStyles, tickledStyles } from '../interaction/tickled-styles.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nexport type {\n AcTokenAddDetail,\n AcTokenAddEvent,\n AcTokenElementEventMap,\n AcTokenItem,\n AcTokenizerFn,\n AcTokenRemoveDetail,\n AcTokenRemoveEvent,\n AcTokensChangeDetail,\n AcTokensChangeEvent,\n} from './types.js';\n\n// ---- Helpers ----\n\nconst DEFAULT_TOKENIZER: AcTokenizerFn = (text: string) => text.split(/[\\s,;]+/);\n\ntype LruCache<K, V> = {\n get: (k: K) => V | undefined;\n set: (k: K, v: V) => void;\n has: (k: K) => boolean;\n clear: () => void;\n};\n\nfunction makeLruCache<K, V>(maxSize: number): LruCache<K, V> {\n const map = new Map<K, V>();\n return {\n get: k => map.get(k),\n set: (k, v) => {\n if (map.has(k))\n map.delete(k);\n map.set(k, v);\n if (map.size > maxSize)\n map.delete(map.keys().next().value!);\n },\n has: k => map.has(k),\n clear: () => map.clear(),\n };\n}\n\n// ---- Component ----\n\n/**\n * Token/tag input with per-token autocomplete suggestions.\n *\n * Users type tokens separated by space, comma or semicolon (default). Each\n * committed token appears as a chip inline with the text cursor. The\n * suggestion popup follows the input cursor position.\n *\n * @fires {AcTokensChangeEvent} ac-token-change — any time the token list changes\n * @fires {AcTokenAddEvent} ac-token-add — when a token is added\n * @fires {AcTokenRemoveEvent} ac-token-remove — when a token is removed\n *\n * @example\n * ```html\n * <ixfx-ac-token placeholder=\"Add tags…\" data-tokens=\"one two three\"></ixfx-ac-token>\n * ```\n */\n@customElement(`ixfx-ac-token`)\nexport class AcTokenElement extends LitElement {\n /** Provides completion results for the current draft token. */\n @property({ type: Object })\n completionProvider: IDataProvider<string, AcTokenItem> | undefined;\n\n /** Custom tokenizer — defaults to splitting on space, comma, semicolon. */\n @property({ type: Object })\n tokenizer: AcTokenizerFn | undefined;\n\n /** Placeholder text shown when no tokens or draft text are present. */\n @property({ type: String })\n placeholder = ``;\n\n /** Maximum number of query results to cache (LRU). */\n @property({ type: Number, attribute: `cache-size` })\n cacheSize = 20;\n\n /** Debounce delay in ms before invoking the provider after keystroke. */\n @property({ type: Number, attribute: `debounce-ms` })\n debounceMs = 150;\n\n /**\n * When true, only suggestions from the popup can be committed.\n * When false (default), typing text and pressing Enter commits it as-is.\n */\n @property({ type: Boolean })\n strict = false;\n\n /**\n * When false (default), tokens that have already been committed are\n * filtered out of the suggestion list. Set to true to show all\n * suggestions including duplicates.\n */\n @property({ type: Boolean, attribute: `allow-duplicates` })\n allowDuplicates = false;\n\n @state() private _tokens: AcTokenItem[] = [];\n @state() private _draft = ``;\n @state() private _selectedTokenIndex: number | undefined;\n @state() private _isOpen = false;\n\n private _tickled = new TickledController<number>(this, {\n getItems: () => this.#data.items.map((_, i) => ({ id: i, enabled: true })),\n });\n\n #data = new DataController<string, AcTokenItem>(this, undefined, {\n clearOnRequest: true,\n onError: err => console.error(`[ixfx-ac-token] completionProvider error:`, err),\n });\n\n #cache: LruCache<string, readonly AcTokenItem[]> = makeLruCache(20);\n #debounceTimer: ReturnType<typeof setTimeout> | undefined;\n #staticProvider: IDataProvider<string, AcTokenItem> | undefined;\n #lastSuggestions: readonly AcTokenItem[] = [];\n\n constructor() {\n super();\n this.#cache = makeLruCache<string, readonly AcTokenItem[]>(this.cacheSize);\n }\n\n // ---- Public API ----\n\n get tokens(): readonly AcTokenItem[] {\n return this._tokens;\n }\n\n set tokens(value: readonly AcTokenItem[]) {\n this._tokens = [...value];\n this.#emitChange();\n }\n\n /**\n * Set the token list programmatically. Unlike the `tokens` property setter,\n * this does not dispatch `ac-token-change` — use it for initialisation or any\n * other programmatic update that should not re-enter a parent's own\n * `ac-token-change` handler.\n */\n setTokens(value: readonly AcTokenItem[]): void {\n this._tokens = [...value];\n }\n\n /** All committed token labels joined with commas. */\n get value(): string {\n return this._tokens.map(t => t.label).join(`, `);\n }\n\n // ---- Lifecycle ----\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.#buildStaticProvider();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.#debounceTimer !== undefined) {\n clearTimeout(this.#debounceTimer);\n this.#debounceTimer = undefined;\n }\n // DataController.cancel() called automatically via hostDisconnected\n }\n\n protected override updated(changedProps: PropertyValues): void {\n if (changedProps.has(`completionProvider`) || changedProps.has(`cacheSize`)) {\n this.#cache = makeLruCache<string, readonly AcTokenItem[]>(this.cacheSize);\n }\n if (changedProps.has(`completionProvider`)) {\n this.#buildStaticProvider();\n }\n // Re-tickle the top suggestion when the list is replaced, so Enter accepts\n // the suggestion the user sees highlighted rather than committing raw draft text.\n if (this.#data.items !== this.#lastSuggestions) {\n this.#lastSuggestions = this.#data.items;\n if (this.#data.items.length > 0) {\n this._tickled.setTickled(0);\n } else {\n this._tickled.clearTickled();\n }\n }\n }\n\n #buildStaticProvider(): void {\n const raw = this.getAttribute(`data-tokens`);\n if (!raw || this.completionProvider) {\n this.#staticProvider = undefined;\n return;\n }\n const items: AcTokenItem[] = raw\n .trim()\n .split(/[\\s,;]+/)\n .filter(Boolean)\n .map(label => ({ label }));\n this.#staticProvider = createAcCompletionProvider(items);\n }\n\n // ---- Handlers ----\n\n #onWrapperClick = (e: MouseEvent): void => {\n const target = e.target as HTMLElement;\n if (!target.closest(`.token-chip`)) {\n this.shadowRoot?.querySelector<HTMLInputElement>(`input.draft`)?.focus();\n }\n };\n\n #onFocus = (): void => {\n this._selectedTokenIndex = undefined;\n this.#scheduleSuggestionFetch(this._draft);\n };\n\n #onBlur = (): void => {\n // Delay so pointerdown on popup items fires first\n setTimeout(() => {\n this._isOpen = false;\n this._tickled.clearTickled();\n this._selectedTokenIndex = undefined;\n }, 120);\n };\n\n #onInput = (e: Event): void => {\n const input = e.target as HTMLInputElement;\n const value = input.value;\n this._selectedTokenIndex = undefined;\n\n const tokenize = this.tokenizer ?? DEFAULT_TOKENIZER;\n const parts = tokenize(value);\n\n if (parts.length > 1) {\n for (let i = 0; i < parts.length - 1; i++) {\n const label = parts[i].trim();\n if (label)\n this.#addToken({ label });\n }\n this._draft = parts[parts.length - 1] ?? ``;\n } else {\n this._draft = value;\n }\n\n this.#scheduleSuggestionFetch(this._draft);\n };\n\n #onKeyDown = (e: KeyboardEvent): void => {\n const input = e.target as HTMLInputElement;\n\n if ((e.metaKey || e.ctrlKey) && e.key === `a`) {\n e.preventDefault();\n const parts = [...this._tokens.map(t => t.label), this._draft.trim()].filter(Boolean);\n navigator.clipboard.writeText(parts.join(` `)).catch(() => {});\n return;\n }\n\n // Printable key while a token chip is selected → edit that token\n if (\n this._selectedTokenIndex !== undefined\n && e.key.length === 1\n && !e.metaKey && !e.ctrlKey && !e.altKey\n ) {\n e.preventDefault();\n this.#startEditingSelectedToken(e.key);\n return;\n }\n\n this.#handleNavigationKey(e, input);\n };\n\n #handleNavigationKey(e: KeyboardEvent, input: HTMLInputElement): void {\n switch (e.key) {\n case `ArrowLeft`: {\n if (input.selectionStart === 0 && input.selectionEnd === 0) {\n e.preventDefault();\n if (this._selectedTokenIndex === undefined) {\n if (this._tokens.length > 0)\n this._selectedTokenIndex = this._tokens.length - 1;\n } else if (this._selectedTokenIndex > 0) {\n this._selectedTokenIndex--;\n }\n }\n break;\n }\n case `ArrowRight`: {\n if (this._selectedTokenIndex !== undefined) {\n e.preventDefault();\n if (this._selectedTokenIndex < this._tokens.length - 1) {\n this._selectedTokenIndex++;\n } else {\n this._selectedTokenIndex = undefined;\n }\n }\n break;\n }\n case `Backspace`: {\n if (input.selectionStart === 0 && input.selectionEnd === 0) {\n e.preventDefault();\n if (this._selectedTokenIndex !== undefined) {\n this.#removeToken(this._selectedTokenIndex);\n } else if (this._tokens.length > 0) {\n this.#removeToken(this._tokens.length - 1);\n }\n }\n break;\n }\n case `Enter`: {\n const tickledIdx = this._tickled.tickledId;\n if (this._isOpen && tickledIdx !== undefined && this.#data.items[tickledIdx]) {\n e.preventDefault();\n this.#selectSuggestion(this.#data.items[tickledIdx] as AcTokenItem);\n } else if (!this.strict && this._draft.trim()) {\n e.preventDefault();\n this.#addToken({ label: this._draft.trim() });\n this._draft = ``;\n this.#closePopup();\n }\n break;\n }\n case `ArrowDown`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n this._tickled.handleKeyboardNavigation(`next`);\n this.#scrollSuggestionIntoView();\n break;\n }\n case `ArrowUp`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n this._tickled.handleKeyboardNavigation(`previous`);\n this.#scrollSuggestionIntoView();\n break;\n }\n case `Escape`: {\n e.preventDefault();\n this.#closePopup();\n this._selectedTokenIndex = undefined;\n break;\n }\n }\n }\n\n #onPaste = (e: ClipboardEvent): void => {\n e.preventDefault();\n const text = e.clipboardData?.getData(`text/plain`) ?? ``;\n if (!text)\n return;\n\n const tokenize = this.tokenizer ?? DEFAULT_TOKENIZER;\n const parts = tokenize(this._draft + text).filter(Boolean);\n if (parts.length === 0)\n return;\n\n if (parts.length === 1) {\n this._draft = parts[0];\n } else {\n for (let i = 0; i < parts.length - 1; i++) {\n const label = parts[i].trim();\n if (label)\n this.#addToken({ label });\n }\n this._draft = parts[parts.length - 1] ?? ``;\n }\n\n this.updateComplete.then(() => {\n this.shadowRoot\n ?.querySelector<HTMLInputElement>(`input.draft`)\n ?.setSelectionRange(this._draft.length, this._draft.length);\n });\n this.#scheduleSuggestionFetch(this._draft);\n };\n\n #onSuggestionPointerDown = (e: PointerEvent, item: AcTokenItem): void => {\n e.preventDefault();\n this.#selectSuggestion(item);\n };\n\n #onChipPointerDown = (e: PointerEvent, index: number): void => {\n if (e.button !== 0)\n return;\n e.preventDefault();\n const el = e.currentTarget as HTMLElement;\n const startY = e.clientY;\n let dragged = false;\n\n el.setPointerCapture(e.pointerId);\n\n const cleanup = (): void => {\n // eslint-disable-next-line ts/no-use-before-define\n el.removeEventListener(`pointermove`, onMove);\n // eslint-disable-next-line ts/no-use-before-define\n el.removeEventListener(`pointerup`, onUp);\n };\n\n const onMove = (me: PointerEvent): void => {\n if (Math.abs(me.clientY - startY) > 28) {\n dragged = true;\n el.releasePointerCapture(me.pointerId);\n cleanup();\n this.#removeToken(index);\n this.shadowRoot?.querySelector<HTMLInputElement>(`input.draft`)?.focus();\n }\n };\n\n const onUp = (): void => {\n cleanup();\n if (!dragged) {\n this._selectedTokenIndex = this._selectedTokenIndex === index ? undefined : index;\n this.shadowRoot?.querySelector<HTMLInputElement>(`input.draft`)?.focus();\n }\n };\n\n el.addEventListener(`pointermove`, onMove);\n el.addEventListener(`pointerup`, onUp);\n };\n\n // ---- Internal logic ----\n\n #startEditingSelectedToken(key: string): void {\n const idx = this._selectedTokenIndex;\n if (idx === undefined)\n return;\n const token = this._tokens[idx];\n if (!token)\n return;\n\n const newDraft = token.label + key;\n this.#removeToken(idx);\n this._selectedTokenIndex = undefined;\n this._draft = newDraft;\n\n this.updateComplete.then(() => {\n const inp = this.shadowRoot?.querySelector<HTMLInputElement>(`input.draft`);\n if (!inp)\n return;\n inp.setSelectionRange(inp.value.length, inp.value.length);\n });\n this.#scheduleSuggestionFetch(newDraft);\n }\n\n #addToken(item: AcTokenItem): void {\n const index = this._tokens.length;\n this._tokens = [...this._tokens, item];\n this.dispatchEvent(new CustomEvent<AcTokenAddDetail>(`ac-token-add`, {\n detail: { item, index },\n bubbles: true,\n composed: true,\n }));\n this.#emitChange();\n }\n\n #removeToken(index: number): void {\n const item = this._tokens[index];\n if (!item)\n return;\n this._tokens = this._tokens.filter((_, i) => i !== index);\n\n if (this._selectedTokenIndex !== undefined) {\n if (this._selectedTokenIndex === index) {\n this._selectedTokenIndex = undefined;\n } else if (this._selectedTokenIndex > index) {\n this._selectedTokenIndex--;\n }\n }\n\n this.dispatchEvent(new CustomEvent<AcTokenRemoveDetail>(`ac-token-remove`, {\n detail: { item, index },\n bubbles: true,\n composed: true,\n }));\n this.#emitChange();\n }\n\n #selectSuggestion(item: AcTokenItem): void {\n this.#addToken(item);\n this._draft = ``;\n this.#closePopup();\n }\n\n #emitChange(): void {\n this.dispatchEvent(new CustomEvent<AcTokensChangeDetail>(`ac-token-change`, {\n detail: { tokens: this._tokens },\n bubbles: true,\n composed: true,\n }));\n }\n\n #filterUsed(items: readonly AcTokenItem[]): readonly AcTokenItem[] {\n if (this.allowDuplicates)\n return items;\n const used = new Set(this._tokens.map(t => t.label));\n return items.filter(item => !used.has(item.label));\n }\n\n #closePopup(): void {\n this._isOpen = false;\n this._tickled.clearTickled();\n }\n\n #cancelPending(): void {\n if (this.#debounceTimer !== undefined) {\n clearTimeout(this.#debounceTimer);\n this.#debounceTimer = undefined;\n }\n this.#data.cancel();\n }\n\n #scheduleSuggestionFetch(query: string): void {\n const cachedProvider = this.#buildCachedProvider();\n if (!cachedProvider) {\n this._isOpen = false;\n return;\n }\n\n if (this.#debounceTimer !== undefined)\n clearTimeout(this.#debounceTimer);\n this._isOpen = true;\n\n this.#debounceTimer = setTimeout(() => {\n this.#data.provider = cachedProvider;\n this.#data.request(query);\n }, this.debounceMs);\n }\n\n #buildCachedProvider(): IDataProvider<string, AcTokenItem> | undefined {\n const raw = this.completionProvider ?? this.#staticProvider;\n if (!raw)\n return undefined;\n\n return (query, signal) => {\n const hit = this.#cache.get(query);\n if (hit !== undefined)\n return this.#filterUsed(hit as AcTokenItem[]);\n\n const result = raw(query, signal);\n\n // Streaming providers pass through uncached\n if (Symbol.asyncIterator in new Object(result))\n return result;\n\n if (Array.isArray(result)) {\n this.#cache.set(query, result);\n return this.#filterUsed(result);\n }\n\n return (result as Promise<readonly AcTokenItem[]>).then((items) => {\n if (!signal.aborted)\n this.#cache.set(query, items);\n return this.#filterUsed(items);\n });\n };\n }\n\n #scrollSuggestionIntoView(): void {\n this.updateComplete.then(() => {\n this.shadowRoot?.querySelector(`.item.tickled`)?.scrollIntoView({ block: `nearest` });\n });\n }\n\n // ---- Render helpers ----\n\n #renderChip(item: AcTokenItem, index: number) {\n const isSelected = this._selectedTokenIndex === index;\n return html`\n <span\n class=\"token-chip ${isSelected ? `selected` : ``}\"\n title=${item.subLabel ?? nothing}\n @pointerdown=${(e: PointerEvent) => this.#onChipPointerDown(e, index)}\n >\n ${item.icon ? html`<ixfx-icon class=\"chip-icon\" name=${item.icon}></ixfx-icon>` : nothing}\n <span class=\"chip-label\">${item.label}</span>\n </span>\n `;\n }\n\n #renderSuggestion(item: AcTokenItem, index: number) {\n const isTickled = this._tickled.isTickled(index);\n return html`\n <div\n class=\"item ${isTickled ? `tickled` : ``}\"\n role=\"option\"\n id=\"ac-token-sugg-${index}\"\n aria-selected=${isTickled}\n @pointerenter=${() => this._tickled.handlePointerEnter(index)}\n @pointerdown=${(e: PointerEvent) => this.#onSuggestionPointerDown(e, item)}\n >\n ${item.icon ? html`<ixfx-icon class=\"sugg-icon\" name=${item.icon}></ixfx-icon>` : nothing}\n <span class=\"sugg-label\">${item.label}</span>\n ${item.subLabel ? html`<span class=\"sugg-sublabel\">${item.subLabel}</span>` : nothing}\n </div>\n `;\n }\n\n #renderPopup() {\n const showEmpty = !this.#data.loading && this.#data.items.length === 0;\n return html`\n <div\n class=\"popup\"\n role=\"listbox\"\n aria-label=\"Suggestions\"\n data-input-mode=${this._tickled.inputMode}\n @pointerleave=${(e: PointerEvent) => this._tickled.handlePointerLeave(e)}\n >\n ${showEmpty\n ? html`<div class=\"no-results\">No matching results</div>`\n : this.#data.items.map((item, i) => this.#renderSuggestion(item as AcTokenItem, i))\n }\n </div>\n `;\n }\n\n protected override render() {\n const tickledIdx = this._tickled.tickledId ?? -1;\n const activeDescendant = tickledIdx >= 0 ? `ac-token-sugg-${tickledIdx}` : undefined;\n const showPlaceholder = this._tokens.length === 0 ? (this.placeholder || nothing) : nothing;\n\n return html`\n <div class=\"wrapper\" @click=${this.#onWrapperClick}>\n ${this._tokens.map((t, i) => this.#renderChip(t, i))}\n <input\n type=\"text\"\n class=\"draft\"\n .value=${this._draft}\n placeholder=${showPlaceholder}\n autocomplete=\"off\"\n spellcheck=\"false\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=${this._isOpen}\n aria-activedescendant=${activeDescendant ?? nothing}\n @input=${this.#onInput}\n @keydown=${this.#onKeyDown}\n @focus=${this.#onFocus}\n @blur=${this.#onBlur}\n @paste=${this.#onPaste}\n >\n ${this.#data.loading ? html`<span class=\"spinner\" aria-hidden=\"true\"></span>` : nothing}\n </div>\n ${this._isOpen ? this.#renderPopup() : nothing}\n `;\n }\n\n static override styles = [\n themeFallbacks,\n tickledStyles,\n tickledItemStyles,\n css`\n :host {\n display: block;\n position: relative;\n font-family: var(--font-family, system-ui, sans-serif);\n font-size: var(--text-m, 12px);\n color: var(--surface-2-text);\n }\n\n /* ---- Wrapper (looks like a text input) ---- */\n\n .wrapper {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ac-token-chip-gap, var(--space-xs, 3px));\n padding: var(--ac-token-input-padding, var(--space-xs, 3px) var(--space-m, 8px));\n background: var(--ac-token-input-background, var(--surface-3, var(--surface-2)));\n color: var(--surface-2-text);\n border: var(--ac-token-input-border, var(--border));\n border-radius: var(--ac-token-input-border-radius, var(--radius-m, 4px));\n cursor: text;\n min-height: 32px;\n box-sizing: border-box;\n transition: border-color var(--transition, 0.15s ease-out);\n }\n\n .wrapper:focus-within {\n border-color: var(--accent);\n }\n\n /* ---- Token chips ---- */\n\n .token-chip {\n display: inline-flex;\n align-items: center;\n gap: var(--space-xs, 3px);\n padding: 1px var(--space-m, 8px);\n background: var(--ac-token-chip-background, var(--surface-4));\n border: var(--ac-token-chip-border, var(--border));\n border-radius: var(--ac-token-chip-border-radius, var(--radius-s, 3px));\n user-select: none;\n cursor: default;\n font-size: var(--text-s, 11px);\n white-space: nowrap;\n touch-action: none;\n transition:\n background var(--transition, 0.1s ease-out),\n border-color var(--transition, 0.1s ease-out),\n color var(--transition, 0.1s ease-out);\n }\n\n .token-chip.selected {\n background: var(--ac-token-chip-selected-background, var(--accent));\n color: var(--ac-token-chip-selected-color, var(--accent-text, #fff));\n border-color: var(--accent);\n }\n\n .chip-icon {\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n }\n\n /* ---- Draft input ---- */\n\n input.draft {\n flex: 1;\n min-width: 60px;\n border: none;\n background: transparent;\n color: inherit;\n font: inherit;\n outline: none;\n caret-color: var(--accent);\n padding: 1px 0;\n anchor-name: --ac-token-draft;\n }\n\n input.draft::placeholder {\n color: var(--surface-muted-text);\n }\n\n /* ---- Spinner ---- */\n\n .spinner {\n width: 12px;\n height: 12px;\n border: 2px solid var(--surface-5);\n border-top-color: var(--accent);\n border-radius: 50%;\n animation: ac-token-spin 0.7s linear infinite;\n flex-shrink: 0;\n pointer-events: none;\n margin-left: var(--space-xs, 3px);\n }\n\n @keyframes ac-token-spin {\n to { transform: rotate(360deg); }\n }\n\n /* ---- Popup ---- */\n\n .popup {\n position: fixed;\n position-anchor: --ac-token-draft;\n top: anchor(bottom);\n left: anchor(left);\n margin-top: 2px;\n position-try-fallbacks: --ac-token-popup-above;\n z-index: 200;\n background: var(--surface-3, var(--surface-2));\n border: var(--border);\n border-radius: var(--radius-m, 4px);\n box-shadow: var(--shadow-l, 0 4px 24px rgba(0, 0, 0, 0.5));\n padding: var(--space-xs, 3px) 0;\n max-height: 260px;\n min-width: 160px;\n overflow-y: auto;\n font-size: var(--ac-token-popup-font-size, var(--text-s, 11px));\n }\n\n @position-try --ac-token-popup-above {\n top: auto;\n bottom: anchor(top);\n left: anchor(left);\n margin-top: 0;\n margin-bottom: 2px;\n }\n\n /* ---- Suggestion items ---- */\n\n .item {\n /* tickledItemStyles provides base; override layout for popup context */\n display: flex;\n padding: var(--item-padding, var(--space-xs, 3px) var(--space-l, 12px));\n gap: var(--space-m, 8px);\n cursor: pointer;\n margin: 0 var(--space-xs, 3px);\n white-space: nowrap;\n min-height: 28px;\n user-select: none;\n }\n\n .sugg-icon {\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n }\n\n .sugg-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sugg-sublabel {\n flex-shrink: 0;\n margin-left: auto;\n color: var(--surface-muted-text);\n font-size: var(--text-s, 11px);\n }\n\n /* ---- Empty state ---- */\n\n .no-results {\n padding: var(--space-m, 8px) var(--space-l, 12px);\n color: var(--surface-muted-text);\n font-style: italic;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-ac-token': AcTokenElement;\n }\n}\n\nexport interface AcTokenElement {\n addEventListener: (<K extends keyof AcTokenElementEventMap>(\n type: K,\n listener: (this: AcTokenElement, event: AcTokenElementEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ) => void) & ((\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ac-token.js","names":["#data","#scheduleSuggestionFetch","#addToken","#startEditingSelectedToken","#handleNavigationKey","#selectSuggestion","#removeToken","#cache","#emitChange","#buildStaticProvider","#debounceTimer","#lastSuggestions","#staticProvider","#closePopup","#scrollSuggestionIntoView","#buildCachedProvider","#filterUsed","#onChipPointerDown","#onSuggestionPointerDown","#renderSuggestion","#onWrapperClick","#renderChip","#onInput","#onKeyDown","#onFocus","#onBlur","#onPaste","#renderPopup","customElement"],"sources":["../src/ac-token/ac-token.ts"],"sourcesContent":["/* eslint-disable ts/no-unsafe-declaration-merging */\nimport type { PropertyValues } from 'lit';\nimport type { IDataProvider } from '../common/data-provider.js';\nimport type {\n AcTokenAddDetail,\n AcTokenElementEventMap,\n AcTokenItem,\n AcTokenizerFn,\n AcTokenRemoveDetail,\n AcTokensChangeDetail,\n} from './types.js';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { DataController } from '../common/data-controller.js';\nimport { createAcCompletionProvider } from '../incr-search/index.js';\nimport { TickledController } from '../interaction/tickled-controller.js';\nimport { tickledItemStyles, tickledStyles } from '../interaction/tickled-styles.js';\nimport { themeFallbacks } from '../styles/fallbacks.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\nimport '../icons/icon.js';\n\nexport type {\n AcTokenAddDetail,\n AcTokenAddEvent,\n AcTokenElementEventMap,\n AcTokenItem,\n AcTokenizerFn,\n AcTokenRemoveDetail,\n AcTokenRemoveEvent,\n AcTokensChangeDetail,\n AcTokensChangeEvent,\n} from './types.js';\n\n// ---- Helpers ----\n\nconst DEFAULT_TOKENIZER: AcTokenizerFn = (text: string) => text.split(/[\\s,;]+/);\n\ntype LruCache<K, V> = {\n get: (k: K) => V | undefined;\n set: (k: K, v: V) => void;\n has: (k: K) => boolean;\n clear: () => void;\n};\n\nfunction makeLruCache<K, V>(maxSize: number): LruCache<K, V> {\n const map = new Map<K, V>();\n return {\n get: k => map.get(k),\n set: (k, v) => {\n if (map.has(k))\n map.delete(k);\n map.set(k, v);\n if (map.size > maxSize)\n map.delete(map.keys().next().value!);\n },\n has: k => map.has(k),\n clear: () => map.clear(),\n };\n}\n\n// ---- Component ----\n\n/**\n * Token/tag input with per-token autocomplete suggestions.\n *\n * Users type tokens separated by space, comma or semicolon (default). Each\n * committed token appears as a chip inline with the text cursor. The\n * suggestion popup follows the input cursor position.\n *\n * @fires {AcTokensChangeEvent} ac-token-change — any time the token list changes\n * @fires {AcTokenAddEvent} ac-token-add — when a token is added\n * @fires {AcTokenRemoveEvent} ac-token-remove — when a token is removed\n *\n * @example\n * ```html\n * <ixfx-ac-token placeholder=\"Add tags…\" data-tokens=\"one two three\"></ixfx-ac-token>\n * ```\n */\n@customElement(`ixfx-ac-token`)\nexport class AcTokenElement extends LitElement {\n /** Provides completion results for the current draft token. */\n @property({ type: Object })\n completionProvider: IDataProvider<string, AcTokenItem> | undefined;\n\n /** Custom tokenizer — defaults to splitting on space, comma, semicolon. */\n @property({ type: Object })\n tokenizer: AcTokenizerFn | undefined;\n\n /** Placeholder text shown when no tokens or draft text are present. */\n @property({ type: String })\n placeholder = ``;\n\n /** Maximum number of query results to cache (LRU). */\n @property({ type: Number, attribute: `cache-size` })\n cacheSize = 20;\n\n /** Debounce delay in ms before invoking the provider after keystroke. */\n @property({ type: Number, attribute: `debounce-ms` })\n debounceMs = 150;\n\n /**\n * When true, only suggestions from the popup can be committed.\n * When false (default), typing text and pressing Enter commits it as-is.\n */\n @property({ type: Boolean })\n strict = false;\n\n /**\n * When false (default), tokens that have already been committed are\n * filtered out of the suggestion list. Set to true to show all\n * suggestions including duplicates.\n */\n @property({ type: Boolean, attribute: `allow-duplicates` })\n allowDuplicates = false;\n\n @state() private _tokens: AcTokenItem[] = [];\n @state() private _draft = ``;\n @state() private _selectedTokenIndex: number | undefined;\n @state() private _isOpen = false;\n\n private _tickled = new TickledController<number>(this, {\n getItems: () => this.#data.items.map((_, i) => ({ id: i, enabled: true })),\n });\n\n #data = new DataController<string, AcTokenItem>(this, undefined, {\n clearOnRequest: true,\n onError: err => console.error(`[ixfx-ac-token] completionProvider error:`, err),\n });\n\n #cache: LruCache<string, readonly AcTokenItem[]> = makeLruCache(20);\n #debounceTimer: ReturnType<typeof setTimeout> | undefined;\n #staticProvider: IDataProvider<string, AcTokenItem> | undefined;\n #lastSuggestions: readonly AcTokenItem[] = [];\n\n constructor() {\n super();\n this.#cache = makeLruCache<string, readonly AcTokenItem[]>(this.cacheSize);\n }\n\n // ---- Public API ----\n\n get tokens(): readonly AcTokenItem[] {\n return this._tokens;\n }\n\n set tokens(value: readonly AcTokenItem[]) {\n this._tokens = [...value];\n this.#emitChange();\n }\n\n /**\n * Set the token list programmatically. Unlike the `tokens` property setter,\n * this does not dispatch `ac-token-change` — use it for initialisation or any\n * other programmatic update that should not re-enter a parent's own\n * `ac-token-change` handler.\n */\n setTokens(value: readonly AcTokenItem[]): void {\n this._tokens = [...value];\n }\n\n /** All committed token labels joined with commas. */\n get value(): string {\n return this._tokens.map(t => t.label).join(`, `);\n }\n\n // ---- Lifecycle ----\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.#buildStaticProvider();\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n if (this.#debounceTimer !== undefined) {\n clearTimeout(this.#debounceTimer);\n this.#debounceTimer = undefined;\n }\n // DataController.cancel() called automatically via hostDisconnected\n }\n\n protected override updated(changedProps: PropertyValues): void {\n if (changedProps.has(`completionProvider`) || changedProps.has(`cacheSize`)) {\n this.#cache = makeLruCache<string, readonly AcTokenItem[]>(this.cacheSize);\n }\n if (changedProps.has(`completionProvider`)) {\n this.#buildStaticProvider();\n }\n // Re-tickle the top suggestion when the list is replaced, so Enter accepts\n // the suggestion the user sees highlighted rather than committing raw draft text.\n if (this.#data.items !== this.#lastSuggestions) {\n this.#lastSuggestions = this.#data.items;\n if (this.#data.items.length > 0) {\n this._tickled.setTickled(0);\n } else {\n this._tickled.clearTickled();\n }\n }\n }\n\n #buildStaticProvider(): void {\n const raw = this.getAttribute(`data-tokens`);\n if (!raw || this.completionProvider) {\n this.#staticProvider = undefined;\n return;\n }\n const items: AcTokenItem[] = raw\n .trim()\n .split(/[\\s,;]+/)\n .filter(Boolean)\n .map(label => ({ label }));\n this.#staticProvider = createAcCompletionProvider(items);\n }\n\n // ---- Handlers ----\n\n #onWrapperClick = (e: MouseEvent): void => {\n const target = e.target as HTMLElement;\n if (!target.closest(`.token-chip`)) {\n this.shadowRoot?.querySelector<HTMLInputElement>(`input.draft`)?.focus();\n }\n };\n\n #onFocus = (): void => {\n this._selectedTokenIndex = undefined;\n this.#scheduleSuggestionFetch(this._draft);\n };\n\n #onBlur = (): void => {\n // Delay so pointerdown on popup items fires first\n setTimeout(() => {\n this._isOpen = false;\n this._tickled.clearTickled();\n this._selectedTokenIndex = undefined;\n }, 120);\n };\n\n #onInput = (e: Event): void => {\n const input = e.target as HTMLInputElement;\n const value = input.value;\n this._selectedTokenIndex = undefined;\n\n const tokenize = this.tokenizer ?? DEFAULT_TOKENIZER;\n const parts = tokenize(value);\n\n if (parts.length > 1) {\n for (let i = 0; i < parts.length - 1; i++) {\n const label = parts[i].trim();\n if (label)\n this.#addToken({ label });\n }\n this._draft = parts[parts.length - 1] ?? ``;\n } else {\n this._draft = value;\n }\n\n this.#scheduleSuggestionFetch(this._draft);\n };\n\n #onKeyDown = (e: KeyboardEvent): void => {\n const input = e.target as HTMLInputElement;\n\n if ((e.metaKey || e.ctrlKey) && e.key === `a`) {\n e.preventDefault();\n const parts = [...this._tokens.map(t => t.label), this._draft.trim()].filter(Boolean);\n navigator.clipboard.writeText(parts.join(` `)).catch(() => {});\n return;\n }\n\n // Printable key while a token chip is selected → edit that token\n if (\n this._selectedTokenIndex !== undefined\n && e.key.length === 1\n && !e.metaKey && !e.ctrlKey && !e.altKey\n ) {\n e.preventDefault();\n this.#startEditingSelectedToken(e.key);\n return;\n }\n\n this.#handleNavigationKey(e, input);\n };\n\n #handleNavigationKey(e: KeyboardEvent, input: HTMLInputElement): void {\n switch (e.key) {\n case `ArrowLeft`: {\n if (input.selectionStart === 0 && input.selectionEnd === 0) {\n e.preventDefault();\n if (this._selectedTokenIndex === undefined) {\n if (this._tokens.length > 0)\n this._selectedTokenIndex = this._tokens.length - 1;\n } else if (this._selectedTokenIndex > 0) {\n this._selectedTokenIndex--;\n }\n }\n break;\n }\n case `ArrowRight`: {\n if (this._selectedTokenIndex !== undefined) {\n e.preventDefault();\n if (this._selectedTokenIndex < this._tokens.length - 1) {\n this._selectedTokenIndex++;\n } else {\n this._selectedTokenIndex = undefined;\n }\n }\n break;\n }\n case `Backspace`: {\n if (input.selectionStart === 0 && input.selectionEnd === 0) {\n e.preventDefault();\n if (this._selectedTokenIndex !== undefined) {\n this.#removeToken(this._selectedTokenIndex);\n } else if (this._tokens.length > 0) {\n this.#removeToken(this._tokens.length - 1);\n }\n }\n break;\n }\n case `Enter`: {\n const tickledIdx = this._tickled.tickledId;\n if (this._isOpen && tickledIdx !== undefined && this.#data.items[tickledIdx]) {\n e.preventDefault();\n this.#selectSuggestion(this.#data.items[tickledIdx] as AcTokenItem);\n } else if (!this.strict && this._draft.trim()) {\n e.preventDefault();\n this.#addToken({ label: this._draft.trim() });\n this._draft = ``;\n this.#closePopup();\n }\n break;\n }\n case `ArrowDown`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n this._tickled.handleKeyboardNavigation(`next`);\n this.#scrollSuggestionIntoView();\n break;\n }\n case `ArrowUp`: {\n if (!this._isOpen)\n return;\n e.preventDefault();\n this._tickled.handleKeyboardNavigation(`previous`);\n this.#scrollSuggestionIntoView();\n break;\n }\n case `Escape`: {\n e.preventDefault();\n this.#closePopup();\n this._selectedTokenIndex = undefined;\n break;\n }\n }\n }\n\n #onPaste = (e: ClipboardEvent): void => {\n e.preventDefault();\n const text = e.clipboardData?.getData(`text/plain`) ?? ``;\n if (!text)\n return;\n\n const tokenize = this.tokenizer ?? DEFAULT_TOKENIZER;\n const parts = tokenize(this._draft + text).filter(Boolean);\n if (parts.length === 0)\n return;\n\n if (parts.length === 1) {\n this._draft = parts[0];\n } else {\n for (let i = 0; i < parts.length - 1; i++) {\n const label = parts[i].trim();\n if (label)\n this.#addToken({ label });\n }\n this._draft = parts[parts.length - 1] ?? ``;\n }\n\n this.updateComplete.then(() => {\n this.shadowRoot\n ?.querySelector<HTMLInputElement>(`input.draft`)\n ?.setSelectionRange(this._draft.length, this._draft.length);\n });\n this.#scheduleSuggestionFetch(this._draft);\n };\n\n #onSuggestionPointerDown = (e: PointerEvent, item: AcTokenItem): void => {\n e.preventDefault();\n this.#selectSuggestion(item);\n };\n\n #onChipPointerDown = (e: PointerEvent, index: number): void => {\n if (e.button !== 0)\n return;\n e.preventDefault();\n const el = e.currentTarget as HTMLElement;\n const startY = e.clientY;\n let dragged = false;\n\n el.setPointerCapture(e.pointerId);\n\n const cleanup = (): void => {\n // eslint-disable-next-line ts/no-use-before-define\n el.removeEventListener(`pointermove`, onMove);\n // eslint-disable-next-line ts/no-use-before-define\n el.removeEventListener(`pointerup`, onUp);\n };\n\n const onMove = (me: PointerEvent): void => {\n if (Math.abs(me.clientY - startY) > 28) {\n dragged = true;\n el.releasePointerCapture(me.pointerId);\n cleanup();\n this.#removeToken(index);\n this.shadowRoot?.querySelector<HTMLInputElement>(`input.draft`)?.focus();\n }\n };\n\n const onUp = (): void => {\n cleanup();\n if (!dragged) {\n this._selectedTokenIndex = this._selectedTokenIndex === index ? undefined : index;\n this.shadowRoot?.querySelector<HTMLInputElement>(`input.draft`)?.focus();\n }\n };\n\n el.addEventListener(`pointermove`, onMove);\n el.addEventListener(`pointerup`, onUp);\n };\n\n // ---- Internal logic ----\n\n #startEditingSelectedToken(key: string): void {\n const idx = this._selectedTokenIndex;\n if (idx === undefined)\n return;\n const token = this._tokens[idx];\n if (!token)\n return;\n\n const newDraft = token.label + key;\n this.#removeToken(idx);\n this._selectedTokenIndex = undefined;\n this._draft = newDraft;\n\n this.updateComplete.then(() => {\n const inp = this.shadowRoot?.querySelector<HTMLInputElement>(`input.draft`);\n if (!inp)\n return;\n inp.setSelectionRange(inp.value.length, inp.value.length);\n });\n this.#scheduleSuggestionFetch(newDraft);\n }\n\n #addToken(item: AcTokenItem): void {\n const index = this._tokens.length;\n this._tokens = [...this._tokens, item];\n this.dispatchEvent(new CustomEvent<AcTokenAddDetail>(`ac-token-add`, {\n detail: { item, index },\n bubbles: true,\n composed: true,\n }));\n this.#emitChange();\n }\n\n #removeToken(index: number): void {\n const item = this._tokens[index];\n if (!item)\n return;\n this._tokens = this._tokens.filter((_, i) => i !== index);\n\n if (this._selectedTokenIndex !== undefined) {\n if (this._selectedTokenIndex === index) {\n this._selectedTokenIndex = undefined;\n } else if (this._selectedTokenIndex > index) {\n this._selectedTokenIndex--;\n }\n }\n\n this.dispatchEvent(new CustomEvent<AcTokenRemoveDetail>(`ac-token-remove`, {\n detail: { item, index },\n bubbles: true,\n composed: true,\n }));\n this.#emitChange();\n }\n\n #selectSuggestion(item: AcTokenItem): void {\n this.#addToken(item);\n this._draft = ``;\n this.#closePopup();\n }\n\n #emitChange(): void {\n this.dispatchEvent(new CustomEvent<AcTokensChangeDetail>(`ac-token-change`, {\n detail: { tokens: this._tokens },\n bubbles: true,\n composed: true,\n }));\n }\n\n #filterUsed(items: readonly AcTokenItem[]): readonly AcTokenItem[] {\n if (this.allowDuplicates)\n return items;\n const used = new Set(this._tokens.map(t => t.label));\n return items.filter(item => !used.has(item.label));\n }\n\n #closePopup(): void {\n this._isOpen = false;\n this._tickled.clearTickled();\n }\n\n #cancelPending(): void {\n if (this.#debounceTimer !== undefined) {\n clearTimeout(this.#debounceTimer);\n this.#debounceTimer = undefined;\n }\n this.#data.cancel();\n }\n\n #scheduleSuggestionFetch(query: string): void {\n const cachedProvider = this.#buildCachedProvider();\n if (!cachedProvider) {\n this._isOpen = false;\n return;\n }\n\n if (this.#debounceTimer !== undefined)\n clearTimeout(this.#debounceTimer);\n this._isOpen = true;\n\n this.#debounceTimer = setTimeout(() => {\n this.#data.provider = cachedProvider;\n this.#data.request(query);\n }, this.debounceMs);\n }\n\n #buildCachedProvider(): IDataProvider<string, AcTokenItem> | undefined {\n const raw = this.completionProvider ?? this.#staticProvider;\n if (!raw)\n return undefined;\n\n return (query, signal) => {\n const hit = this.#cache.get(query);\n if (hit !== undefined)\n return this.#filterUsed(hit as AcTokenItem[]);\n\n const result = raw(query, signal);\n\n // Streaming providers pass through uncached\n if (Symbol.asyncIterator in new Object(result))\n return result;\n\n if (Array.isArray(result)) {\n this.#cache.set(query, result);\n return this.#filterUsed(result);\n }\n\n return (result as Promise<readonly AcTokenItem[]>).then((items) => {\n if (!signal.aborted)\n this.#cache.set(query, items);\n return this.#filterUsed(items);\n });\n };\n }\n\n #scrollSuggestionIntoView(): void {\n this.updateComplete.then(() => {\n this.shadowRoot?.querySelector(`.item.tickled`)?.scrollIntoView({ block: `nearest` });\n });\n }\n\n // ---- Render helpers ----\n\n #renderChip(item: AcTokenItem, index: number) {\n const isSelected = this._selectedTokenIndex === index;\n return html`\n <span\n class=\"token-chip ${isSelected ? `selected` : ``}\"\n title=${item.subLabel ?? nothing}\n @pointerdown=${(e: PointerEvent) => this.#onChipPointerDown(e, index)}\n >\n ${item.icon ? html`<ixfx-icon class=\"chip-icon\" name=${item.icon}></ixfx-icon>` : nothing}\n <span class=\"chip-label\">${item.label}</span>\n </span>\n `;\n }\n\n #renderSuggestion(item: AcTokenItem, index: number) {\n const isTickled = this._tickled.isTickled(index);\n return html`\n <div\n class=\"item ${isTickled ? `tickled` : ``}\"\n role=\"option\"\n id=\"ac-token-sugg-${index}\"\n aria-selected=${isTickled}\n @pointerenter=${() => this._tickled.handlePointerEnter(index)}\n @pointerdown=${(e: PointerEvent) => this.#onSuggestionPointerDown(e, item)}\n >\n ${item.icon ? html`<ixfx-icon class=\"sugg-icon\" name=${item.icon}></ixfx-icon>` : nothing}\n <span class=\"sugg-label\">${item.label}</span>\n ${item.subLabel ? html`<span class=\"sugg-sublabel\">${item.subLabel}</span>` : nothing}\n </div>\n `;\n }\n\n #renderPopup() {\n const showEmpty = !this.#data.loading && this.#data.items.length === 0;\n return html`\n <div\n class=\"popup\"\n role=\"listbox\"\n aria-label=\"Suggestions\"\n data-input-mode=${this._tickled.inputMode}\n @pointerleave=${(e: PointerEvent) => this._tickled.handlePointerLeave(e)}\n >\n ${showEmpty\n ? html`<div class=\"no-results\">No matching results</div>`\n : this.#data.items.map((item, i) => this.#renderSuggestion(item as AcTokenItem, i))\n }\n </div>\n `;\n }\n\n protected override render() {\n const tickledIdx = this._tickled.tickledId ?? -1;\n const activeDescendant = tickledIdx >= 0 ? `ac-token-sugg-${tickledIdx}` : undefined;\n const showPlaceholder = this._tokens.length === 0 ? (this.placeholder || nothing) : nothing;\n\n return html`\n <div class=\"wrapper\" @click=${this.#onWrapperClick}>\n ${this._tokens.map((t, i) => this.#renderChip(t, i))}\n <input\n type=\"text\"\n class=\"draft\"\n .value=${this._draft}\n placeholder=${showPlaceholder}\n autocomplete=\"off\"\n spellcheck=\"false\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=${this._isOpen}\n aria-activedescendant=${activeDescendant ?? nothing}\n @input=${this.#onInput}\n @keydown=${this.#onKeyDown}\n @focus=${this.#onFocus}\n @blur=${this.#onBlur}\n @paste=${this.#onPaste}\n >\n ${this.#data.loading ? html`<span class=\"spinner\" aria-hidden=\"true\"></span>` : nothing}\n </div>\n ${this._isOpen ? this.#renderPopup() : nothing}\n `;\n }\n\n static override styles = [\n themeFallbacks,\n tickledStyles,\n tickledItemStyles,\n css`\n :host {\n display: block;\n position: relative;\n font-family: var(--font-family, system-ui, sans-serif);\n font-size: var(--text-m, 12px);\n color: var(--surface-2-text);\n }\n\n /* ---- Wrapper (looks like a text input) ---- */\n\n .wrapper {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--ac-token-chip-gap, var(--space-xs, 3px));\n padding: var(--ac-token-input-padding, var(--space-xs, 3px) var(--space-m, 8px));\n background: var(--ac-token-input-background, var(--surface-3, var(--surface-2)));\n color: var(--surface-2-text);\n border: var(--ac-token-input-border, var(--border));\n border-radius: var(--ac-token-input-border-radius, var(--radius-m, 4px));\n cursor: text;\n min-height: 32px;\n box-sizing: border-box;\n transition: border-color var(--transition, 0.15s ease-out);\n }\n\n .wrapper:focus-within {\n border-color: var(--accent);\n }\n\n /* ---- Token chips ---- */\n\n .token-chip {\n display: inline-flex;\n align-items: center;\n gap: var(--space-xs, 3px);\n padding: 1px var(--space-m, 8px);\n background: var(--ac-token-chip-background, var(--surface-4));\n border: var(--ac-token-chip-border, var(--border));\n border-radius: var(--ac-token-chip-border-radius, var(--radius-s, 3px));\n user-select: none;\n cursor: default;\n font-size: var(--text-s, 11px);\n white-space: nowrap;\n touch-action: none;\n transition:\n background var(--transition, 0.1s ease-out),\n border-color var(--transition, 0.1s ease-out),\n color var(--transition, 0.1s ease-out);\n }\n\n .token-chip.selected {\n background: var(--ac-token-chip-selected-background, var(--accent));\n color: var(--ac-token-chip-selected-color, var(--accent-text, #fff));\n border-color: var(--accent);\n }\n\n .chip-icon {\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n }\n\n /* ---- Draft input ---- */\n\n input.draft {\n flex: 1;\n min-width: 60px;\n border: none;\n background: transparent;\n color: inherit;\n font: inherit;\n outline: none;\n caret-color: var(--accent);\n padding: 1px 0;\n anchor-name: --ac-token-draft;\n }\n\n input.draft::placeholder {\n color: var(--surface-muted-text);\n }\n\n /* ---- Spinner ---- */\n\n .spinner {\n width: 12px;\n height: 12px;\n border: 2px solid var(--surface-5);\n border-top-color: var(--accent);\n border-radius: 50%;\n animation: ac-token-spin 0.7s linear infinite;\n flex-shrink: 0;\n pointer-events: none;\n margin-left: var(--space-xs, 3px);\n }\n\n @keyframes ac-token-spin {\n to { transform: rotate(360deg); }\n }\n\n /* ---- Popup ---- */\n\n .popup {\n position: fixed;\n position-anchor: --ac-token-draft;\n top: anchor(bottom);\n left: anchor(left);\n margin-top: 2px;\n position-try-fallbacks: --ac-token-popup-above;\n z-index: 200;\n background: var(--surface-3, var(--surface-2));\n border: var(--border);\n border-radius: var(--radius-m, 4px);\n box-shadow: var(--shadow-l, 0 4px 24px rgba(0, 0, 0, 0.5));\n padding: var(--space-xs, 3px) 0;\n max-height: 260px;\n min-width: 160px;\n overflow-y: auto;\n font-size: var(--ac-token-popup-font-size, var(--text-s, 11px));\n }\n\n @position-try --ac-token-popup-above {\n top: auto;\n bottom: anchor(top);\n left: anchor(left);\n margin-top: 0;\n margin-bottom: 2px;\n }\n\n /* ---- Suggestion items ---- */\n\n .item {\n /* tickledItemStyles provides base; override layout for popup context */\n display: flex;\n padding: var(--item-padding, var(--space-xs, 3px) var(--space-l, 12px));\n gap: var(--space-m, 8px);\n cursor: pointer;\n margin: 0 var(--space-xs, 3px);\n white-space: nowrap;\n min-height: 28px;\n user-select: none;\n }\n\n .sugg-icon {\n flex-shrink: 0;\n width: 1em;\n height: 1em;\n }\n\n .sugg-label {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .sugg-sublabel {\n flex-shrink: 0;\n margin-left: auto;\n color: var(--surface-muted-text);\n font-size: var(--text-s, 11px);\n }\n\n /* ---- Empty state ---- */\n\n .no-results {\n padding: var(--space-m, 8px) var(--space-l, 12px);\n color: var(--surface-muted-text);\n font-style: italic;\n }\n `,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-ac-token': AcTokenElement;\n }\n}\n\nexport interface AcTokenElement {\n addEventListener: (<K extends keyof AcTokenElementEventMap>(\n type: K,\n listener: (this: AcTokenElement, event: AcTokenElementEventMap[K]) => void,\n options?: boolean | AddEventListenerOptions,\n ) => void) & ((\n type: string,\n listener: EventListenerOrEventListenerObject,\n options?: boolean | AddEventListenerOptions,\n ) => void);\n}\n"],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
2
- import { o as getIcon } from "./defaults-BCiDhZbF.js";
2
+ import { t as getIcon } from "./registry-CkW7q09Q.js";
3
+ import "./icons.js";
3
4
  import { t as prominenceStyles } from "./prominence-DlFShic3.js";
4
5
  import { LitElement, css, html, nothing } from "lit";
5
6
  import { property } from "lit/decorators.js";
@@ -27,7 +28,7 @@ const buttonStyles = css`
27
28
  outline: var(--ixfx-button-outline, none);
28
29
  border-radius: var(--radius-xl, 8px);
29
30
  corner-shape: superellipse(1);
30
- padding: var(--space-m, 8px) var(--space-l, 12px);
31
+ padding: var(--ixfx-button-padding-block, var(--space-m, 8px)) var(--ixfx-button-padding-inline, var(--space-l, 12px));
31
32
  font-family: var(--font-family, inherit);
32
33
  font-size: var(--text-m, 14px);
33
34
  margin: 0;
@@ -147,4 +148,4 @@ ButtonElement = __decorate([safeCustomElement(`ixfx-button`)], ButtonElement);
147
148
  //#endregion
148
149
  export { buttonStyles as n, ButtonElement as t };
149
150
 
150
- //# sourceMappingURL=button-Bn0BuLpO.js.map
151
+ //# sourceMappingURL=button-Dat2yHAU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button-Dat2yHAU.js","names":["customElement"],"sources":["../src/button/button-styles.ts","../src/button/button.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const buttonStyles = css`\n :host {\n display: inline-flex;\n max-width: 100%;\n vertical-align: middle;\n user-select: none;\n -webkit-user-select: none;\n }\n\n :host([hidden]) {\n display: none;\n }\n\n button {\n cursor: pointer;\n appearance: none;\n background: var(--surface-4, #ccc);\n color: var(--surface-3-text, #000);\n border: var(--border, 1px solid #999);\n outline: var(--ixfx-button-outline, none);\n border-radius: var(--radius-xl, 8px);\n corner-shape: superellipse(1);\n padding: var(--ixfx-button-padding-block, var(--space-m, 8px)) var(--ixfx-button-padding-inline, var(--space-l, 12px));\n font-family: var(--font-family, inherit);\n font-size: var(--text-m, 14px);\n margin: 0;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.5em;\n width: 100%;\n overflow: hidden;\n white-space: nowrap;\n box-shadow: \n var(--ixfx-button-shade, none),\n inset 1px 1px 1px 1px color-mix(in oklch, var(--surface-4) 30%, transparent), inset -1px -1px 1px 1px color-mix(in oklch, var(--surface-2) 20%, transparent),\n 2px 2px 1px 0px color-mix(in oklch, var(--surface-2) 30%, transparent);\n transition: background var(--transition, 0.2s), border-color var(--transition, 0.2s);\n }\n\n button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n\n button:hover:not(:disabled) {\n background: color-mix(in oklch, var(--surface-4) 80%, transparent);\n border-color: var(--accent, #666);\n box-shadow: \n inset 1px 1px 1px 1px color-mix(in oklch, var(--surface-5) 70%, transparent), \n inset -1px -1px 1px 1px color-mix(in oklch, var(--surface-2) 60%, transparent),\n 2px 2px 1px 0px color-mix(in oklch, var(--surface-2) 90%, transparent);\n }\n\n button:active:not(:disabled) {\n background: var(--surface-2, #aaa);\n transform: translateY(1px);\n box-shadow: inset 1px 1px 0px 0.5px color-mix(in oklch,var(--surface-1),transparent);\n }\n\n .button-icon {\n display: var(--ixfx-button-hide-icon, inline-flex);\n align-items: center;\n flex-shrink: 0;\n }\n\n .button-label {\n white-space: nowrap;\n }\n\n :host([has-icon]) .button-label {\n display: var(--ixfx-button-hide-label, inline);\n }\n\n :host([hide-label]) .button-label {\n display: none;\n }\n\n :host([hide-icon]) .button-icon {\n display: none;\n }\n\n :host([subtle]) button {\n background: color-mix(in oklch, var(--surface-4, #ccc) 40%, transparent);\n }\n\n :host([subtle]) button:hover:not(:disabled),\n :host([subtle]) button:focus-visible:not(:disabled) {\n background: color-mix(in oklch, var(--surface-4, #ccc) 70%, transparent);\n }\n`;\n","import { html, LitElement, nothing } from \"lit\";\nimport { property } from \"lit/decorators.js\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport { getIcon } from \"../icons/index.js\";\nimport { prominenceStyles } from \"../styles/prominence.js\";\nimport { safeCustomElement as customElement } from \"../util/custom-elements.js\";\nimport { buttonStyles } from \"./button-styles.js\";\n\n@customElement(`ixfx-button`)\nexport class ButtonElement extends LitElement {\n @property({ type: Boolean })\n disabled = false;\n\n @property({ type: String })\n icon?: string;\n\n @property({ type: Boolean, attribute: `hide-icon`, reflect: true })\n hideIcon = false;\n\n @property({ type: Boolean, attribute: `hide-label`, reflect: true })\n hideLabel = false;\n\n @property({ type: Boolean, attribute: `has-icon`, reflect: true })\n hasIcon = false;\n\n @property({ type: Boolean, reflect: true })\n subtle = false;\n\n protected _renderIcon() {\n if (this.hideIcon || !this.icon)\n return nothing;\n\n if (this.icon.startsWith(`<svg`)) {\n return html`<span class=\"button-icon\">${unsafeHTML(this.icon)}</span>`;\n }\n\n const svg = getIcon(this.icon);\n\n if (!svg)\n return nothing;\n\n return html`<ixfx-icon class=\"button-icon\" name=\"${this.icon}\"></ixfx-icon>`;\n }\n\n protected render() {\n this.hasIcon = !this.hideIcon && !!this.icon;\n const label = this.hideLabel\n ? nothing\n : html`<span class=\"button-label\"><slot></slot></span>`;\n return html`<button ?disabled=${this.disabled}>${this._renderIcon()}${label}</button>`;\n }\n\n static styles = [\n prominenceStyles,\n buttonStyles,\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"ixfx-button\": ButtonElement;\n }\n}\n"],"mappings":";;;;;;;;AAEA,MAAa,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACOxB,IAAM,gBAAN,MAAM,sBAAsB,WAAW;;;EAEjC,KAAA,WAAA;EAMA,KAAA,WAAA;EAGC,KAAA,YAAA;EAGF,KAAA,UAAA;EAGD,KAAA,SAAA;;CAET,cAAwB;EACtB,IAAI,KAAK,YAAY,CAAC,KAAK,MACzB,OAAO;EAET,IAAI,KAAK,KAAK,WAAW,MAAM,GAC7B,OAAO,IAAI,6BAA6B,WAAW,KAAK,IAAI,EAAE;EAKhE,IAAI,CAFQ,QAAQ,KAAK,IAElB,GACL,OAAO;EAET,OAAO,IAAI,wCAAwC,KAAK,KAAK;CAC/D;CAEA,SAAmB;EACjB,KAAK,UAAU,CAAC,KAAK,YAAY,CAAC,CAAC,KAAK;EACxC,MAAM,QAAQ,KAAK,YACf,UACA,IAAI;EACR,OAAO,IAAI,qBAAqB,KAAK,SAAS,GAAG,KAAK,YAAY,IAAI,MAAM;CAC9E;;EAEgB,KAAA,SAAA,CACd,kBACA,YACF;;AACF;AA9CG,WAAA,CAAA,SAAS,EAAE,MAAM,QAAQ,CAAC,CAAA,GAAA,cAAA,WAAA,YAAA,KAAA,CAAA;AAG1B,WAAA,CAAA,SAAS,EAAE,MAAM,OAAO,CAAC,CAAA,GAAA,cAAA,WAAA,QAAA,KAAA,CAAA;AAGzB,WAAA,CAAA,SAAS;CAAE,MAAM;CAAS,WAAW;CAAa,SAAS;AAAK,CAAC,CAAA,GAAA,cAAA,WAAA,YAAA,KAAA,CAAA;AAGjE,WAAA,CAAA,SAAS;CAAE,MAAM;CAAS,WAAW;CAAc,SAAS;AAAK,CAAC,CAAA,GAAA,cAAA,WAAA,aAAA,KAAA,CAAA;AAGlE,WAAA,CAAA,SAAS;CAAE,MAAM;CAAS,WAAW;CAAY,SAAS;AAAK,CAAC,CAAA,GAAA,cAAA,WAAA,WAAA,KAAA,CAAA;AAGhE,WAAA,CAAA,SAAS;CAAE,MAAM;CAAS,SAAS;AAAK,CAAC,CAAA,GAAA,cAAA,WAAA,UAAA,KAAA,CAAA;AAjB3CA,gBAAAA,WAAAA,CAAAA,kBAAc,aAAa,CAAA,GAAA,aAAA"}
package/dist/button.js CHANGED
@@ -1,2 +1,2 @@
1
- import { t as ButtonElement } from "./button-Bn0BuLpO.js";
1
+ import { t as ButtonElement } from "./button-Dat2yHAU.js";
2
2
  export { ButtonElement };
package/dist/checkbox.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as themeFallbacks } from "./fallbacks-DEE1nCTt.js";
1
+ import { t as themeFallbacks } from "./fallbacks-DNI9xt0F.js";
2
2
  import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
3
3
  import { t as prominenceStyles } from "./prominence-DlFShic3.js";
4
4
  import { LitElement, css, html } from "lit";
@@ -1,7 +1,8 @@
1
- import { t as themeFallbacks } from "./fallbacks-DEE1nCTt.js";
1
+ import { t as themeFallbacks } from "./fallbacks-DNI9xt0F.js";
2
2
  import { t as popupSurfaceStyles } from "./popup-D80sj2QC.js";
3
3
  import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
4
- import { n as ICON_CHECK } from "./defaults-BCiDhZbF.js";
4
+ import { n as ICON_CHECK } from "./defaults-BkWCPJFL.js";
5
+ import "./labelled-range-input.js";
5
6
  import { LitElement, css, html, nothing } from "lit";
6
7
  import { property, query, state } from "lit/decorators.js";
7
8
  import { unsafeHTML } from "lit/directives/unsafe-html.js";
@@ -932,4 +933,4 @@ ColourPickerPopup = __decorate([safeCustomElement(`ixfx-colour-picker-popup`)],
932
933
  //#endregion
933
934
  export { ColourPicker as n, ColourPickerPopup as t };
934
935
 
935
- //# sourceMappingURL=colour-picker-0stHB90J.js.map
936
+ //# sourceMappingURL=colour-picker-BSDBL-QL.js.map