@ixfx/components 0.5.19 → 0.6.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 (198) hide show
  1. package/bundle/index.d.ts +462 -210
  2. package/bundle/index.d.ts.map +1 -1
  3. package/bundle/index.js +8027 -6493
  4. package/bundle/index.js.map +1 -1
  5. package/dist/ac-text.js +3 -3
  6. package/dist/ac-token-DVbmHmky.d.ts +107 -0
  7. package/dist/ac-token-DVbmHmky.d.ts.map +1 -0
  8. package/dist/ac-token.d.ts +2 -0
  9. package/dist/ac-token.js +646 -0
  10. package/dist/ac-token.js.map +1 -0
  11. package/dist/{button-CphdEaZd.js → button-Bn0BuLpO.js} +2 -3
  12. package/dist/{button-CphdEaZd.js.map → button-Bn0BuLpO.js.map} +1 -1
  13. package/dist/button.d.ts +1 -1
  14. package/dist/button.d.ts.map +1 -1
  15. package/dist/button.js +1 -1
  16. package/dist/checkbox.js +1 -1
  17. package/dist/{colour-picker-37NyVenk.js → colour-picker-0stHB90J.js} +18 -8
  18. package/dist/colour-picker-0stHB90J.js.map +1 -0
  19. package/dist/colour-picker.d.ts +1 -1
  20. package/dist/colour-picker.js +1 -1
  21. package/dist/crumbs.d.ts +2 -2
  22. package/dist/crumbs.js +1152 -1
  23. package/dist/crumbs.js.map +1 -0
  24. package/dist/data-controller-DOlmqNKb.js +171 -0
  25. package/dist/data-controller-DOlmqNKb.js.map +1 -0
  26. package/dist/data-display.js +1 -1
  27. package/dist/data-grid-BeAkORz2.d.ts +215 -0
  28. package/dist/data-grid-BeAkORz2.d.ts.map +1 -0
  29. package/dist/data-grid.d.ts +2 -0
  30. package/dist/data-grid.js +1225 -0
  31. package/dist/data-grid.js.map +1 -0
  32. package/dist/data-provider-BAn_-oR1.d.ts +61 -0
  33. package/dist/data-provider-BAn_-oR1.d.ts.map +1 -0
  34. package/dist/{defaults-BkWCPJFL.js → defaults-BCiDhZbF.js} +20 -3
  35. package/dist/defaults-BCiDhZbF.js.map +1 -0
  36. package/dist/drag-ghost-DtSDvjri.js +85 -0
  37. package/dist/drag-ghost-DtSDvjri.js.map +1 -0
  38. package/dist/editable-label.js +1 -1
  39. package/dist/{incr-search-2pz21xtR.js → element-search-Y8SRfPGM.js} +2 -133
  40. package/dist/element-search-Y8SRfPGM.js.map +1 -0
  41. package/dist/fallbacks-DEE1nCTt.js +406 -0
  42. package/dist/fallbacks-DEE1nCTt.js.map +1 -0
  43. package/dist/form-CsXJX15p.js +64 -0
  44. package/dist/form-CsXJX15p.js.map +1 -0
  45. package/dist/form.d.ts +15 -0
  46. package/dist/form.d.ts.map +1 -0
  47. package/dist/form.js +2 -0
  48. package/dist/grouped-item-lister-CNLMgdIr.d.ts +121 -0
  49. package/dist/grouped-item-lister-CNLMgdIr.d.ts.map +1 -0
  50. package/dist/grouped-item-lister.d.ts +2 -0
  51. package/dist/grouped-item-lister.js +177 -0
  52. package/dist/grouped-item-lister.js.map +1 -0
  53. package/dist/{icon-DG9Lm3LT.js → icons-Bm2ByQ3s.js} +6 -3
  54. package/dist/icons-Bm2ByQ3s.js.map +1 -0
  55. package/dist/icons.js +2 -8
  56. package/dist/incr-search-vCzuao-2.js +137 -0
  57. package/dist/incr-search-vCzuao-2.js.map +1 -0
  58. package/dist/incr-search.d.ts +1 -1
  59. package/dist/incr-search.js +2 -1
  60. package/dist/{index-BKAlRgbq.d.ts → index-BOUaDIW-.d.ts} +4 -1
  61. package/dist/index-BOUaDIW-.d.ts.map +1 -0
  62. package/dist/{index-D9u_Q7-b.d.ts → index-Cu5i8zZY.d.ts} +3 -3
  63. package/dist/{index-D9u_Q7-b.d.ts.map → index-Cu5i8zZY.d.ts.map} +1 -1
  64. package/dist/{index-DkhBGHgF.d.ts → index-ovq_GTdl.d.ts} +2 -2
  65. package/dist/{index-DkhBGHgF.d.ts.map → index-ovq_GTdl.d.ts.map} +1 -1
  66. package/dist/index.d.ts +54 -572
  67. package/dist/index.d.ts.map +1 -1
  68. package/dist/index.js +1898 -4253
  69. package/dist/index.js.map +1 -1
  70. package/dist/labelled-radial-input.d.ts +1 -1
  71. package/dist/labelled-radial-input.js +1 -2
  72. package/dist/labelled-radial-input.js.map +1 -1
  73. package/dist/led.d.ts +0 -1
  74. package/dist/led.d.ts.map +1 -1
  75. package/dist/led.js +2 -4
  76. package/dist/led.js.map +1 -1
  77. package/dist/menu-DIfU70AA.js +1609 -0
  78. package/dist/menu-DIfU70AA.js.map +1 -0
  79. package/dist/menu-item-BG5w7fi4.d.ts.map +1 -1
  80. package/dist/menu.d.ts +1 -1
  81. package/dist/menu.js +1 -2
  82. package/dist/miller.d.ts +3 -3
  83. package/dist/miller.js +3 -3
  84. package/dist/narrowed-text.d.ts.map +1 -1
  85. package/dist/narrowed-text.js +4 -4
  86. package/dist/narrowed-text.js.map +1 -1
  87. package/dist/notification-pill-DyZydXoZ.d.ts +68 -0
  88. package/dist/notification-pill-DyZydXoZ.d.ts.map +1 -0
  89. package/dist/notifier.d.ts +2 -0
  90. package/dist/notifier.js +146 -0
  91. package/dist/notifier.js.map +1 -0
  92. package/dist/panel.js +1 -2
  93. package/dist/panel.js.map +1 -1
  94. package/dist/plots.js +1 -1
  95. package/dist/polar-pad.d.ts +1 -1
  96. package/dist/polar-pad.js +1 -1
  97. package/dist/{radial-input-BhZeyyP-.d.ts → radial-input-DXMN55Nz.d.ts} +2 -2
  98. package/dist/{radial-input-BhZeyyP-.d.ts.map → radial-input-DXMN55Nz.d.ts.map} +1 -1
  99. package/dist/{radial-input-CVxGH-Cp.js → radial-input-Dk8Wydp5.js} +4 -4
  100. package/dist/radial-input-Dk8Wydp5.js.map +1 -0
  101. package/dist/radial-input.d.ts +1 -1
  102. package/dist/radial-input.js +1 -1
  103. package/dist/range-input.d.ts +1 -1
  104. package/dist/range-input.js +1 -1
  105. package/dist/range.d.ts +1 -1
  106. package/dist/range.js +1 -1
  107. package/dist/scroll-fade-CAs1EabA.js +70 -0
  108. package/dist/scroll-fade-CAs1EabA.js.map +1 -0
  109. package/dist/select-horiz.d.ts +50 -0
  110. package/dist/select-horiz.d.ts.map +1 -0
  111. package/dist/select-horiz.js +263 -0
  112. package/dist/select-horiz.js.map +1 -0
  113. package/dist/{slider-input-CzmSVgm7.js → slider-input-CT4gcF-o.js} +2 -2
  114. package/dist/{slider-input-CzmSVgm7.js.map → slider-input-CT4gcF-o.js.map} +1 -1
  115. package/dist/{slider-input-TidGhvXt.d.ts → slider-input-XppH3vcy.d.ts} +2 -2
  116. package/dist/{slider-input-TidGhvXt.d.ts.map → slider-input-XppH3vcy.d.ts.map} +1 -1
  117. package/dist/slider-input.d.ts +1 -1
  118. package/dist/slider-input.js +1 -1
  119. package/dist/snackbar.d.ts +58 -0
  120. package/dist/snackbar.d.ts.map +1 -0
  121. package/dist/snackbar.js +265 -0
  122. package/dist/snackbar.js.map +1 -0
  123. package/dist/split-layout.js +1 -1
  124. package/dist/swipe.d.ts +1 -1
  125. package/dist/swipe.js +1 -1
  126. package/dist/tabs.js +533 -1
  127. package/dist/tabs.js.map +1 -0
  128. package/dist/{tickled-controller-BF2Ea0DE.d.ts → tickled-controller-BtevrRLV.d.ts} +8 -6
  129. package/dist/tickled-controller-BtevrRLV.d.ts.map +1 -0
  130. package/dist/{tickled-styles-fNDdqf6l.js → tickled-controller-DkAU-0qL.js} +19 -105
  131. package/dist/tickled-controller-DkAU-0qL.js.map +1 -0
  132. package/dist/tickled-styles-BrAHEj1q.js +89 -0
  133. package/dist/tickled-styles-BrAHEj1q.js.map +1 -0
  134. package/dist/transitory-label.d.ts +30 -0
  135. package/dist/transitory-label.d.ts.map +1 -0
  136. package/dist/transitory-label.js +249 -0
  137. package/dist/transitory-label.js.map +1 -0
  138. package/dist/{tree-BtiiDX1a.js → tree-BO6BXI2b.js} +4 -4
  139. package/dist/{tree-BtiiDX1a.js.map → tree-BO6BXI2b.js.map} +1 -1
  140. package/dist/{tree-component-DQ9vzdy5.d.ts → tree-component-BvV4muxx.d.ts} +2 -2
  141. package/dist/{tree-component-DQ9vzdy5.d.ts.map → tree-component-BvV4muxx.d.ts.map} +1 -1
  142. package/dist/tree.d.ts +3 -3
  143. package/dist/tree.js +1 -1
  144. package/dist/{types-DO3gt5vg.d.ts → types-Bc23SI94.d.ts} +3 -61
  145. package/dist/types-Bc23SI94.d.ts.map +1 -0
  146. package/dist/types-DlVNJez_.d.ts +41 -0
  147. package/dist/types-DlVNJez_.d.ts.map +1 -0
  148. package/dist/vertical-list.d.ts +122 -0
  149. package/dist/vertical-list.d.ts.map +1 -0
  150. package/dist/vertical-list.js +737 -0
  151. package/dist/vertical-list.js.map +1 -0
  152. package/dist/wheel-nudge-BlSCe_hD.js.map +1 -1
  153. package/dist/{wheel-nudge-DgMTRYlh.d.ts → wheel-nudge-DGrNzWuE.d.ts} +3 -3
  154. package/dist/wheel-nudge-DGrNzWuE.d.ts.map +1 -0
  155. package/dist/{xy-axis-CxHC8z5E.js → xy-axis-B6yMjckW.js} +3 -109
  156. package/dist/xy-axis-B6yMjckW.js.map +1 -0
  157. package/dist/xy-pad.d.ts +1 -1
  158. package/dist/xy-pad.js +1 -1
  159. package/docs-user/README.md +3 -2
  160. package/docs-user/ac-token.md +7 -1
  161. package/docs-user/colour-picker.md +8 -4
  162. package/docs-user/data-grid.md +248 -0
  163. package/docs-user/index.json +217 -0
  164. package/docs-user/llms.txt +57 -0
  165. package/docs-user/menu.md +11 -8
  166. package/docs-user/rating.md +102 -0
  167. package/llms.txt +57 -0
  168. package/package.json +21 -11
  169. package/dist/colour-picker-37NyVenk.js.map +0 -1
  170. package/dist/crumb-navigation-BrB0r14u.js +0 -1220
  171. package/dist/crumb-navigation-BrB0r14u.js.map +0 -1
  172. package/dist/defaults-BkWCPJFL.js.map +0 -1
  173. package/dist/fallbacks-DPgPEqo8.js +0 -218
  174. package/dist/fallbacks-DPgPEqo8.js.map +0 -1
  175. package/dist/icon-DG9Lm3LT.js.map +0 -1
  176. package/dist/icons.js.map +0 -1
  177. package/dist/incr-search-2pz21xtR.js.map +0 -1
  178. package/dist/index-BKAlRgbq.d.ts.map +0 -1
  179. package/dist/interaction-D6efrBLo.js +0 -1
  180. package/dist/menu-CdwSe_XN.js +0 -825
  181. package/dist/menu-CdwSe_XN.js.map +0 -1
  182. package/dist/menu-item-CrmUwIoJ.js +0 -782
  183. package/dist/menu-item-CrmUwIoJ.js.map +0 -1
  184. package/dist/radial-input-CVxGH-Cp.js.map +0 -1
  185. package/dist/registry-CkW7q09Q.js +0 -21
  186. package/dist/registry-CkW7q09Q.js.map +0 -1
  187. package/dist/selecthorizontal.d.ts +0 -15
  188. package/dist/selecthorizontal.d.ts.map +0 -1
  189. package/dist/selecthorizontal.js +0 -43
  190. package/dist/selecthorizontal.js.map +0 -1
  191. package/dist/tab-list-mAoD6L0e.js +0 -615
  192. package/dist/tab-list-mAoD6L0e.js.map +0 -1
  193. package/dist/tickled-controller-BF2Ea0DE.d.ts.map +0 -1
  194. package/dist/tickled-styles-fNDdqf6l.js.map +0 -1
  195. package/dist/types-DO3gt5vg.d.ts.map +0 -1
  196. package/dist/wheel-nudge-DgMTRYlh.d.ts.map +0 -1
  197. package/dist/xy-axis-CxHC8z5E.js.map +0 -1
  198. package/docs-user/selecthorizontal.md +0 -32
@@ -1,4 +1,3 @@
1
- import { css } from "lit";
2
1
  //#region src/interaction/tickled-controller.ts
3
2
  /**
4
3
  * ReactiveController that manages "tickled" state for interactive lists.
@@ -15,10 +14,11 @@ import { css } from "lit";
15
14
  *
16
15
  * ## Global Mouse Tracking
17
16
  *
18
- * This controller uses a singleton global `pointermove` listener to track actual
19
- * mouse movement. This prevents `pointerenter` events caused by content scrolling
20
- * from incorrectly switching to mouse mode when the user is actually using keyboard
21
- * navigation.
17
+ * This controller uses a single, ref-counted global `pointermove` listener (shared
18
+ * across all instances) to track actual mouse movement. This prevents `pointerenter`
19
+ * events caused by content scrolling from incorrectly switching to mouse mode when
20
+ * the user is actually using keyboard navigation. The listener is attached when the
21
+ * first host connects and removed once the last host disconnects.
22
22
  *
23
23
  * @example
24
24
  * ```ts
@@ -65,7 +65,12 @@ var TickledController = class TickledController {
65
65
  this._mouseMovedSinceKeyboard = true;
66
66
  }
67
67
  static {
68
- this._globalListenerAttached = false;
68
+ this._listenerRefCount = 0;
69
+ }
70
+ static {
71
+ this._onGlobalPointerMove = (e) => {
72
+ TickledController.handleGlobalPointerMove(e.clientX, e.clientY);
73
+ };
69
74
  }
70
75
  constructor(host, config) {
71
76
  this._tickledId = void 0;
@@ -75,14 +80,13 @@ var TickledController = class TickledController {
75
80
  host.addController(this);
76
81
  }
77
82
  hostConnected() {
78
- if (!TickledController._globalListenerAttached) {
79
- document.addEventListener(`pointermove`, (e) => {
80
- TickledController.handleGlobalPointerMove(e.clientX, e.clientY);
81
- }, { passive: true });
82
- TickledController._globalListenerAttached = true;
83
- }
83
+ if (TickledController._listenerRefCount === 0) document.addEventListener(`pointermove`, TickledController._onGlobalPointerMove, { passive: true });
84
+ TickledController._listenerRefCount++;
85
+ }
86
+ hostDisconnected() {
87
+ TickledController._listenerRefCount--;
88
+ if (TickledController._listenerRefCount === 0) document.removeEventListener(`pointermove`, TickledController._onGlobalPointerMove);
84
89
  }
85
- hostDisconnected() {}
86
90
  /**
87
91
  * Get the current input mode
88
92
  */
@@ -216,96 +220,6 @@ var TickledController = class TickledController {
216
220
  }
217
221
  };
218
222
  //#endregion
219
- //#region src/interaction/tickled-styles.ts
220
- /**
221
- * Shared CSS styles for tickled interaction pattern.
222
- *
223
- * Tickled state is controlled via the `.tickled` CSS class (applied by TickledController).
224
- * The `tickledItemStyles` provides base styling that all tickled components should use.
225
- *
226
- * ## CSS Variable Contract
227
- *
228
- * **Style variables (default values defined in `tickledItemStyles`):**
229
- * - `--item-bg`: Default background (default: transparent)
230
- * - `--item-bg-tickled`: Background when tickled (default: rgba(0, 0, 0, 0.06))
231
- * - `--item-bg-selected`: Background when selected (default: rgba(25, 118, 210, 1))
232
- * - `--item-bg-selected-tickled`: Background when selected AND tickled (default: rgba(21, 101, 192, 1))
233
- * - `--item-border`: Border style (default: 1px solid transparent)
234
- * - `--item-border-tickled`: Border when tickled (default: 1px solid var(--accent))
235
- * - `--item-border-selected`: Border when selected (default: 1px solid rgba(25, 118, 210, 1))
236
- * - `--item-text-tickled`: Text color when tickled (default: inherit)
237
- * - `--item-text-selected`: Text color when selected (default: #fff)
238
- * - `--item-padding`: Item padding (default: 4px 8px)
239
- * - `--item-border-radius`: Border radius (default: 4px)
240
- * - `--item-icon-spacing`: Gap between icon and text (default: 4px)
241
- *
242
- * ## Usage
243
- *
244
- * Components should import both `tickledStyles` and `tickledItemStyles`:
245
- *
246
- * ```ts
247
- * import { tickledStyles, tickledItemStyles } from '../interaction/index.js';
248
- *
249
- * class MyComponent extends LitElement {
250
- * static styles = [
251
- * tickledStyles,
252
- * tickledItemStyles,
253
- * css`
254
- * :host {
255
- * --item-bg-tickled: #e0e0e0;
256
- * --item-bg-selected: #1976d2;
257
- * }
258
- * `
259
- * ];
260
- * }
261
- * ```
262
- */
263
- const tickledStyles = css`
264
- /**
265
- * No suppression needed - tickled styling is always active.
266
- */
267
- `;
268
- /**
269
- * Shared item styling for tickled components.
270
- *
271
- * Provides base styles for interactive items with tickled and selected states.
272
- * Components should import this in addition to `tickledStyles` and can override
273
- * CSS variables to customize appearance.
274
- */
275
- const tickledItemStyles = css`
276
- .item {
277
- display: inline-flex;
278
- align-items: center;
279
- gap: var(--item-icon-spacing);
280
- padding: var(--item-padding);
281
- background: var(--item-bg);
282
- border: var(--item-border);
283
- border-radius: var(--item-border-radius);
284
- cursor: pointer;
285
- user-select: none;
286
- white-space: nowrap;
287
- transition: background var(--transition, 0.1s ease-out), border-color var(--transition, 0.1s ease-out);
288
- }
289
-
290
- .item.tickled {
291
- background: var(--item-bg-tickled);
292
- border-color: var(--item-border-tickled);
293
- color: var(--item-text-tickled);
294
- }
295
-
296
- .item.selected {
297
- background: var(--item-bg-selected);
298
- border-color: var(--item-border-selected);
299
- color: var(--item-text-selected);
300
- }
301
-
302
- .item.selected.tickled {
303
- background: var(--item-bg-selected-tickled);
304
- outline: 2px dashed var(--surface-3);
305
- outline-offset: -2px;
306
- }
307
- `;
308
- //#endregion
309
- export { tickledStyles as n, TickledController as r, tickledItemStyles as t };
223
+ export { TickledController as t };
310
224
 
311
- //# sourceMappingURL=tickled-styles-fNDdqf6l.js.map
225
+ //# sourceMappingURL=tickled-controller-DkAU-0qL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tickled-controller-DkAU-0qL.js","names":[],"sources":["../src/interaction/tickled-controller.ts"],"sourcesContent":["import type { ReactiveController, ReactiveControllerHost } from 'lit';\n\n/**\n * Represents an item that can be tickled (highlighted via hover or keyboard navigation)\n */\nexport type TickledItem<T = unknown> = {\n /**\n * Unique identifier for the item (e.g., index, id, path)\n */\n readonly id: T;\n\n /**\n * Whether the item is currently enabled/interactive\n */\n readonly enabled?: boolean;\n};\n\n/**\n * Input mode determines which mechanism controls the tickled state\n */\nexport type InputMode = `keyboard` | `mouse`;\n\n/**\n * Configuration for TickledController\n */\nexport type TickledControllerConfig<T> = {\n /**\n * Function to retrieve all items that can be tickled\n */\n getItems: () => ReadonlyArray<TickledItem<T>>;\n\n /**\n * Optional callback when an item becomes tickled\n * Use this for side effects like opening submenus\n * @param id - The id of the newly tickled item, or undefined if nothing is tickled\n */\n onTickle?: (id: T | undefined) => void;\n\n /**\n * Optional callback fired after any state change (tickled id or input mode)\n * Use this to sync DOM attributes for slotted content that can't use reactive rendering\n *\n * For components that render items directly, this is usually not needed as\n * Lit's reactive rendering will handle updates automatically via requestUpdate()\n *\n * @example\n * ```ts\n * onStateChange: () => {\n * // Sync data-tickled attributes for slotted items\n * const items = this.getItems();\n * items.forEach((item, i) => {\n * if (this.tickled.isTickled(i)) {\n * item.setAttribute('data-tickled', '');\n * } else {\n * item.removeAttribute('data-tickled');\n * }\n * });\n * }\n * ```\n */\n onStateChange?: () => void;\n\n /**\n * Optional initial input mode (defaults to 'mouse')\n */\n initialInputMode?: InputMode;\n};\n\n/**\n * ReactiveController that manages \"tickled\" state for interactive lists.\n *\n * A \"tickled\" item is one that is under active attention via hover (mouse mode)\n * or keyboard focus (keyboard mode). Only one item can be tickled at a time.\n *\n * The input mode determines which mechanism controls tickled state:\n * - Mouse mode: hover controls tickled, keyboard navigation ignored\n * - Keyboard mode: keyboard navigation controls tickled, hover ignored\n *\n * Last interaction wins - any mouse hover switches to mouse mode, any keyboard\n * navigation switches to keyboard mode.\n *\n * ## Global Mouse Tracking\n *\n * This controller uses a single, ref-counted global `pointermove` listener (shared\n * across all instances) to track actual mouse movement. This prevents `pointerenter`\n * events caused by content scrolling from incorrectly switching to mouse mode when\n * the user is actually using keyboard navigation. The listener is attached when the\n * first host connects and removed once the last host disconnects.\n *\n * @example\n * ```ts\n * class MyList extends LitElement {\n * private tickled = new TickledController(this, {\n * getItems: () => this.items.map((item, i) => ({ id: i, enabled: !item.disabled })),\n * onTickle: (id) => {\n * // Optional: perform side effect when item is tickled\n * console.log('Tickled item:', id);\n * }\n * });\n *\n * render() {\n * return html`\n * <ul @pointerleave=${(e) => this.tickled.handlePointerLeave(e)}>\n * ${this.items.map((item, i) => html`\n * <li\n * class=\"item ${this.tickled.isTickled(i) ? 'tickled' : ''}\"\n * @pointerenter=${() => this.tickled.handlePointerEnter(i)}\n * >${item.label}</li>\n * `)}\n * </ul>\n * `;\n * }\n *\n * private handleKeyDown(e: KeyboardEvent) {\n * if (e.key === 'ArrowDown') {\n * this.tickled.handleKeyboardNavigation('next');\n * } else if (e.key === 'ArrowUp') {\n * this.tickled.handleKeyboardNavigation('previous');\n * }\n * }\n * }\n * ```\n */\nexport class TickledController<T = number> implements ReactiveController {\n private host: ReactiveControllerHost;\n private config: TickledControllerConfig<T>;\n private _tickledId: T | undefined = undefined;\n private _inputMode: InputMode;\n\n private static _lastMouseClientX: number = Number.NaN;\n private static _lastMouseClientY: number = Number.NaN;\n private static _mouseMovedSinceKeyboard: boolean = true;\n private static _listenerRefCount: number = 0;\n\n private static readonly _onGlobalPointerMove = (e: PointerEvent): void => {\n TickledController.handleGlobalPointerMove(e.clientX, e.clientY);\n };\n\n constructor(host: ReactiveControllerHost, config: TickledControllerConfig<T>) {\n this.host = host;\n this.config = config;\n this._inputMode = config.initialInputMode ?? `mouse`;\n host.addController(this);\n }\n\n hostConnected(): void {\n if (TickledController._listenerRefCount === 0) {\n document.addEventListener(`pointermove`, TickledController._onGlobalPointerMove, { passive: true });\n }\n TickledController._listenerRefCount++;\n }\n\n hostDisconnected(): void {\n TickledController._listenerRefCount--;\n if (TickledController._listenerRefCount === 0) {\n document.removeEventListener(`pointermove`, TickledController._onGlobalPointerMove);\n }\n }\n\n /**\n * Get the current input mode\n */\n get inputMode(): InputMode {\n return this._inputMode;\n }\n\n /**\n * Get the currently tickled item id\n */\n get tickledId(): T | undefined {\n return this._tickledId;\n }\n\n /**\n * Check if a specific item is tickled\n */\n isTickled(id: T): boolean {\n return this._tickledId === id;\n }\n\n /**\n * Handle global pointer move event.\n * Called automatically by the global listener.\n * Tracks mouse movement to distinguish real hover from content scrolling.\n */\n private static handleGlobalPointerMove(clientX: number, clientY: number): void {\n if (!Number.isNaN(TickledController._lastMouseClientX)) {\n if (\n clientX !== TickledController._lastMouseClientX\n || clientY !== TickledController._lastMouseClientY\n ) {\n TickledController._mouseMovedSinceKeyboard = true;\n }\n }\n TickledController._lastMouseClientX = clientX;\n TickledController._lastMouseClientY = clientY;\n }\n\n /**\n * Check if actual mouse movement has occurred since last keyboard interaction.\n * Used to distinguish real hover/leave from content-scrolling-induced events.\n */\n static get hasMouseMovedSinceKeyboard(): boolean {\n return TickledController._mouseMovedSinceKeyboard;\n }\n\n /**\n * Handle pointer enter event on an item (mouse hover).\n * Only processes if actual mouse movement is detected (not content scrolling).\n * Switches to mouse mode and tickles the item.\n */\n handlePointerEnter(id: T): void {\n if (!TickledController._mouseMovedSinceKeyboard) {\n return;\n }\n\n const items = this.config.getItems();\n const item = items.find(item => item.id === id);\n if (item && item.enabled === false) {\n return;\n }\n\n const modeChanged = this._inputMode !== `mouse`;\n this._inputMode = `mouse`;\n\n const previousId = this._tickledId;\n this._tickledId = id;\n\n this.host.requestUpdate();\n\n if (previousId !== id && this.config.onTickle) {\n this.config.onTickle(id);\n }\n\n if ((previousId !== id || modeChanged) && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n\n /**\n * Handle pointer leave event on an item.\n * Only clears tickled state if actual mouse movement is detected.\n * @param _e The pointer event (not used, but kept for API compatibility)\n */\n handlePointerLeave(_e: PointerEvent): void {\n if (TickledController._mouseMovedSinceKeyboard) {\n this.clearTickled();\n }\n }\n\n /**\n * Handle keyboard navigation.\n * Switches to keyboard mode and moves tickled state.\n *\n * @param direction - 'next', 'previous', 'first', 'last', or specific id\n */\n handleKeyboardNavigation(direction: `next` | `previous` | `first` | `last` | T): void {\n const modeChanged = this._inputMode !== `keyboard`;\n this._inputMode = `keyboard`;\n\n const items = this.config.getItems();\n const enabledItems = items.filter(item => item.enabled !== false);\n\n if (enabledItems.length === 0) {\n return;\n }\n\n let newId: T | undefined;\n\n if (direction === `first`) {\n newId = enabledItems[0].id;\n } else if (direction === `last`) {\n newId = enabledItems.at(-1)?.id;\n } else if (direction === `next` || direction === `previous`) {\n const currentIndex = enabledItems.findIndex(item => item.id === this._tickledId);\n\n if (currentIndex === -1) {\n newId = direction === `next` ? enabledItems[0].id : enabledItems.at(-1)?.id;\n } else {\n const delta = direction === `next` ? 1 : -1;\n const newIndex = currentIndex + delta;\n\n if (newIndex >= 0 && newIndex < enabledItems.length) {\n newId = enabledItems[newIndex].id;\n }\n // If newIndex is out of bounds, keep current tickled item\n }\n } else {\n const item = enabledItems.find(item => item.id === direction);\n if (item) {\n newId = item.id;\n }\n }\n\n if (newId !== undefined) {\n const previousId = this._tickledId;\n this._tickledId = newId;\n this.host.requestUpdate();\n\n if (previousId !== newId && this.config.onTickle) {\n this.config.onTickle(newId);\n }\n\n if ((previousId !== newId || modeChanged) && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n\n /**\n * Manually set the tickled item (useful for programmatic control).\n * Does NOT change input mode.\n */\n setTickled(id: T | undefined): void {\n const previousId = this._tickledId;\n this._tickledId = id;\n this.host.requestUpdate();\n\n if (previousId !== id && this.config.onTickle) {\n this.config.onTickle(id);\n }\n\n if (previousId !== id && this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n\n /**\n * Clear the tickled state (e.g., on pointer leave).\n * Note: For pointer leave events, prefer using handlePointerLeave() which\n * checks for actual mouse movement.\n */\n clearTickled(): void {\n if (this._tickledId !== undefined) {\n this._tickledId = undefined;\n this.host.requestUpdate();\n\n if (this.config.onTickle) {\n this.config.onTickle(undefined);\n }\n\n if (this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n\n /**\n * Manually set the input mode.\n * When switching to keyboard mode, resets the mouse movement tracking.\n */\n setInputMode(mode: InputMode): void {\n if (this._inputMode !== mode) {\n this._inputMode = mode;\n this.host.requestUpdate();\n\n if (mode === `keyboard`) {\n TickledController._mouseMovedSinceKeyboard = false;\n }\n\n if (this.config.onStateChange) {\n this.config.onStateChange();\n }\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ import { css } from "lit";
2
+ //#region src/interaction/tickled-styles.ts
3
+ /**
4
+ * Shared CSS styles for tickled interaction pattern.
5
+ *
6
+ * Tickled state is controlled via the `.tickled` CSS class (applied by TickledController).
7
+ * The `tickledItemStyles` provides base styling that all tickled components should use.
8
+ *
9
+ * ## CSS Variable Contract
10
+ *
11
+ * **Style variables** — `tickledItemStyles` only consumes these via `var()`; it
12
+ * defines no defaults itself. Fallback values (used when no theme CSS is loaded)
13
+ * are registered in `themeFallbacks` (`../styles/fallbacks.ts`) and mirror the
14
+ * documented base theme in `user-theming.md`:
15
+ * - `--item-bg`, `--item-bg-tickled`, `--item-bg-selected`, `--item-bg-selected-tickled`
16
+ * - `--item-border`, `--item-border-tickled`, `--item-border-selected` (full border shorthands, not colours)
17
+ * - `--item-text-tickled`, `--item-text-selected`
18
+ * - `--item-padding`, `--item-border-radius`, `--item-icon-spacing`
19
+ *
20
+ * ## Usage
21
+ *
22
+ * Components should import both `tickledStyles` and `tickledItemStyles`:
23
+ *
24
+ * ```ts
25
+ * import { tickledStyles, tickledItemStyles } from '../interaction/index.js';
26
+ *
27
+ * class MyComponent extends LitElement {
28
+ * static styles = [
29
+ * tickledStyles,
30
+ * tickledItemStyles,
31
+ * css`
32
+ * :host {
33
+ * --item-bg-tickled: #e0e0e0;
34
+ * --item-bg-selected: #1976d2;
35
+ * }
36
+ * `
37
+ * ];
38
+ * }
39
+ * ```
40
+ */
41
+ const tickledStyles = css`
42
+ /**
43
+ * No suppression needed - tickled styling is always active.
44
+ */
45
+ `;
46
+ /**
47
+ * Shared item styling for tickled components.
48
+ *
49
+ * Provides base styles for interactive items with tickled and selected states.
50
+ * Components should import this in addition to `tickledStyles` and can override
51
+ * CSS variables to customize appearance.
52
+ */
53
+ const tickledItemStyles = css`
54
+ .item {
55
+ display: inline-flex;
56
+ align-items: center;
57
+ gap: var(--item-icon-spacing);
58
+ padding: var(--item-padding);
59
+ background: var(--item-bg);
60
+ border: var(--item-border);
61
+ border-radius: var(--item-border-radius);
62
+ cursor: pointer;
63
+ user-select: none;
64
+ white-space: nowrap;
65
+ transition: background var(--transition, 0.1s ease-out), border-color var(--transition, 0.1s ease-out);
66
+ }
67
+
68
+ .item.tickled {
69
+ background: var(--item-bg-tickled);
70
+ border: var(--item-border-tickled);
71
+ color: var(--item-text-tickled);
72
+ }
73
+
74
+ .item.selected {
75
+ background: var(--item-bg-selected);
76
+ border: var(--item-border-selected);
77
+ color: var(--item-text-selected);
78
+ }
79
+
80
+ .item.selected.tickled {
81
+ background: var(--item-bg-selected-tickled);
82
+ outline: 2px dashed var(--surface-3);
83
+ outline-offset: -2px;
84
+ }
85
+ `;
86
+ //#endregion
87
+ export { tickledStyles as n, tickledItemStyles as t };
88
+
89
+ //# sourceMappingURL=tickled-styles-BrAHEj1q.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tickled-styles-BrAHEj1q.js","names":[],"sources":["../src/interaction/tickled-styles.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * Shared CSS styles for tickled interaction pattern.\n *\n * Tickled state is controlled via the `.tickled` CSS class (applied by TickledController).\n * The `tickledItemStyles` provides base styling that all tickled components should use.\n *\n * ## CSS Variable Contract\n *\n * **Style variables** — `tickledItemStyles` only consumes these via `var()`; it\n * defines no defaults itself. Fallback values (used when no theme CSS is loaded)\n * are registered in `themeFallbacks` (`../styles/fallbacks.ts`) and mirror the\n * documented base theme in `user-theming.md`:\n * - `--item-bg`, `--item-bg-tickled`, `--item-bg-selected`, `--item-bg-selected-tickled`\n * - `--item-border`, `--item-border-tickled`, `--item-border-selected` (full border shorthands, not colours)\n * - `--item-text-tickled`, `--item-text-selected`\n * - `--item-padding`, `--item-border-radius`, `--item-icon-spacing`\n *\n * ## Usage\n *\n * Components should import both `tickledStyles` and `tickledItemStyles`:\n *\n * ```ts\n * import { tickledStyles, tickledItemStyles } from '../interaction/index.js';\n *\n * class MyComponent extends LitElement {\n * static styles = [\n * tickledStyles,\n * tickledItemStyles,\n * css`\n * :host {\n * --item-bg-tickled: #e0e0e0;\n * --item-bg-selected: #1976d2;\n * }\n * `\n * ];\n * }\n * ```\n */\n\nexport const tickledStyles = css`\n /**\n * No suppression needed - tickled styling is always active.\n */\n`;\n\n/**\n * Shared item styling for tickled components.\n *\n * Provides base styles for interactive items with tickled and selected states.\n * Components should import this in addition to `tickledStyles` and can override\n * CSS variables to customize appearance.\n */\nexport const tickledItemStyles = css`\n .item {\n display: inline-flex;\n align-items: center;\n gap: var(--item-icon-spacing);\n padding: var(--item-padding);\n background: var(--item-bg);\n border: var(--item-border);\n border-radius: var(--item-border-radius);\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n transition: background var(--transition, 0.1s ease-out), border-color var(--transition, 0.1s ease-out);\n }\n\n .item.tickled {\n background: var(--item-bg-tickled);\n border: var(--item-border-tickled);\n color: var(--item-text-tickled);\n }\n\n .item.selected {\n background: var(--item-bg-selected);\n border: var(--item-border-selected);\n color: var(--item-text-selected);\n }\n\n .item.selected.tickled {\n background: var(--item-bg-selected-tickled);\n outline: 2px dashed var(--surface-3);\n outline-offset: -2px;\n }\n`;"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyCA,MAAa,gBAAgB,GAAG;;;;;;;;;;;;AAahC,MAAa,oBAAoB,GAAG"}
@@ -0,0 +1,30 @@
1
+ import { LitElement, PropertyValues } from "lit";
2
+ //#region src/transitory-label/transitory-label.d.ts
3
+ type Effect = `slide-right` | `slide-left` | `slide-up` | `slide-down` | `fade` | `character-swap`;
4
+ declare class TransitoryLabelElement extends LitElement {
5
+ #private;
6
+ text: string;
7
+ effect: Effect;
8
+ duration: number;
9
+ easing: string;
10
+ private _currentText;
11
+ private _outgoingText;
12
+ private _activeEffect;
13
+ private _transitionId;
14
+ private _queue;
15
+ private _pendingEffect;
16
+ setText(msg: string, effect: Effect): void;
17
+ protected updated(changed: PropertyValues): void;
18
+ private _startTransition;
19
+ private _onTransitionEnd;
20
+ protected render(): import("lit").TemplateResult<1>;
21
+ static styles: import("lit").CSSResult;
22
+ }
23
+ declare global {
24
+ interface HTMLElementTagNameMap {
25
+ 'ixfx-transitory-label': TransitoryLabelElement;
26
+ }
27
+ }
28
+ //#endregion
29
+ export { Effect, TransitoryLabelElement };
30
+ //# sourceMappingURL=transitory-label.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transitory-label.d.ts","names":[],"sources":["../src/transitory-label/transitory-label.ts"],"mappings":";;KAMY;cAKC,+BAA+B;;EACd;EACA,QAAQ;EACR;EACA;UAEX;UACA;UACA;UACA;UAET;UACA;EAER,QAAQ,aAAa,QAAQ;YAKV,QAAQ,SAAS;UAa5B;UAWA;YAgDW,wBAAM;SA4BT,sBAAM;;QAuIhB;YACI;IACR,yBAAyB"}
@@ -0,0 +1,249 @@
1
+ import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
2
+ import { LitElement, css, html, nothing } from "lit";
3
+ import { property, state } from "lit/decorators.js";
4
+ import { keyed } from "lit/directives/keyed.js";
5
+ //#region src/transitory-label/transitory-label.ts
6
+ let TransitoryLabelElement = class TransitoryLabelElement extends LitElement {
7
+ constructor(..._args) {
8
+ super(..._args);
9
+ this.text = ``;
10
+ this.effect = `fade`;
11
+ this.duration = 300;
12
+ this.easing = `ease`;
13
+ this._currentText = ``;
14
+ this._outgoingText = ``;
15
+ this._transitionId = 0;
16
+ this._queue = [];
17
+ this.#onOutgoingEnd = () => {
18
+ this._onTransitionEnd();
19
+ };
20
+ this.#onLastCharOut = () => {
21
+ this._onTransitionEnd();
22
+ };
23
+ }
24
+ setText(msg, effect) {
25
+ this._pendingEffect = effect;
26
+ this.text = msg;
27
+ }
28
+ updated(changed) {
29
+ if (changed.has(`text`) && this.text !== this._currentText) {
30
+ const effect = this._pendingEffect ?? this.effect;
31
+ this._pendingEffect = void 0;
32
+ if (this._activeEffect !== void 0) this._queue.push({
33
+ text: this.text,
34
+ effect
35
+ });
36
+ else this._startTransition(this.text, effect);
37
+ }
38
+ }
39
+ _startTransition(newText, effect) {
40
+ const prevText = this._currentText;
41
+ this._currentText = newText;
42
+ this._outgoingText = prevText;
43
+ if (prevText !== ``) {
44
+ this._transitionId++;
45
+ this._activeEffect = effect;
46
+ }
47
+ }
48
+ _onTransitionEnd() {
49
+ this._outgoingText = ``;
50
+ this._activeEffect = void 0;
51
+ if (this._queue.length > 0) {
52
+ const next = this._queue.shift();
53
+ this._startTransition(next.text, next.effect);
54
+ }
55
+ }
56
+ #onOutgoingEnd;
57
+ #onLastCharOut;
58
+ #renderCharSwap() {
59
+ const charDuration = Math.round(this.duration * .3);
60
+ const charStagger = Math.round(this.duration * .1);
61
+ const currentChars = this._currentText.split(``);
62
+ const outgoingChars = this._outgoingText.split(``);
63
+ const lastIdx = outgoingChars.length - 1;
64
+ const charStyle = (i) => `animation-duration:${charDuration}ms;animation-delay:${i * charStagger}ms;animation-timing-function:${this.easing}`;
65
+ return html`
66
+ ${keyed(`cc${this._transitionId}`, html`
67
+ <span class="layer current char-swap">
68
+ ${currentChars.map((ch, i) => html`<span class="char in" style=${charStyle(i)}>${ch}</span>`)}
69
+ </span>
70
+ `)}
71
+ ${this._outgoingText ? keyed(this._transitionId, html`
72
+ <span class="layer outgoing char-swap">
73
+ ${outgoingChars.map((ch, i) => html`<span
74
+ class="char out"
75
+ style=${charStyle(i)}
76
+ @animationend=${i === lastIdx ? this.#onLastCharOut : void 0}
77
+ >${ch}</span>`)}
78
+ </span>
79
+ `) : nothing}
80
+ `;
81
+ }
82
+ render() {
83
+ if (this._activeEffect === `character-swap`) return html`<span class="container">${this.#renderCharSwap()}</span>`;
84
+ const effect = this._activeEffect ?? ``;
85
+ const durStyle = this._activeEffect ? `animation-duration:${this.duration}ms;animation-timing-function:${this.easing}` : ``;
86
+ return html`
87
+ <span class="container">
88
+ ${this._outgoingText ? keyed(this._transitionId, html`
89
+ <span class="layer outgoing ${effect}" style=${durStyle} @animationend=${this.#onOutgoingEnd}>
90
+ ${this._outgoingText}
91
+ </span>
92
+ `) : nothing}
93
+ ${keyed(`c${this._transitionId}`, html`
94
+ <span class="layer current ${effect}" style=${durStyle}>
95
+ ${this._currentText}
96
+ </span>
97
+ `)}
98
+ </span>
99
+ `;
100
+ }
101
+ static {
102
+ this.styles = css`
103
+ :host {
104
+ display: inline-block;
105
+ --transitory-label-easing: ease;
106
+ }
107
+
108
+ .container {
109
+ display: inline-grid;
110
+ overflow: hidden;
111
+ }
112
+
113
+ .layer {
114
+ grid-area: 1 / 1;
115
+ white-space: nowrap;
116
+ }
117
+
118
+ .layer.outgoing {
119
+ pointer-events: none;
120
+ }
121
+
122
+ /* slide-right */
123
+ .layer.current.slide-right {
124
+ transform: translateX(-100%);
125
+ animation: tl-slide-in-left var(--transitory-label-easing) forwards;
126
+ }
127
+ .layer.outgoing.slide-right {
128
+ animation: tl-slide-out-right var(--transitory-label-easing) forwards;
129
+ }
130
+
131
+ @keyframes tl-slide-in-left {
132
+ from { transform: translateX(-100%); }
133
+ to { transform: translateX(0); }
134
+ }
135
+ @keyframes tl-slide-out-right {
136
+ from { transform: translateX(0); }
137
+ to { transform: translateX(100%); }
138
+ }
139
+
140
+ /* slide-left */
141
+ .layer.current.slide-left {
142
+ transform: translateX(100%);
143
+ animation: tl-slide-in-right var(--transitory-label-easing) forwards;
144
+ }
145
+ .layer.outgoing.slide-left {
146
+ animation: tl-slide-out-left var(--transitory-label-easing) forwards;
147
+ }
148
+
149
+ @keyframes tl-slide-in-right {
150
+ from { transform: translateX(100%); }
151
+ to { transform: translateX(0); }
152
+ }
153
+ @keyframes tl-slide-out-left {
154
+ from { transform: translateX(0); }
155
+ to { transform: translateX(-100%); }
156
+ }
157
+
158
+ /* slide-up */
159
+ .layer.current.slide-up {
160
+ transform: translateY(100%);
161
+ animation: tl-slide-in-bottom var(--transitory-label-easing) forwards;
162
+ }
163
+ .layer.outgoing.slide-up {
164
+ animation: tl-slide-out-top var(--transitory-label-easing) forwards;
165
+ }
166
+
167
+ @keyframes tl-slide-in-bottom {
168
+ from { transform: translateY(100%); }
169
+ to { transform: translateY(0); }
170
+ }
171
+ @keyframes tl-slide-out-top {
172
+ from { transform: translateY(0); }
173
+ to { transform: translateY(-100%); }
174
+ }
175
+
176
+ /* slide-down */
177
+ .layer.current.slide-down {
178
+ transform: translateY(-100%);
179
+ animation: tl-slide-in-top var(--transitory-label-easing) forwards;
180
+ }
181
+ .layer.outgoing.slide-down {
182
+ animation: tl-slide-out-bottom var(--transitory-label-easing) forwards;
183
+ }
184
+
185
+ @keyframes tl-slide-in-top {
186
+ from { transform: translateY(-100%); }
187
+ to { transform: translateY(0); }
188
+ }
189
+ @keyframes tl-slide-out-bottom {
190
+ from { transform: translateY(0); }
191
+ to { transform: translateY(100%); }
192
+ }
193
+
194
+ /* fade */
195
+ .layer.current.fade {
196
+ opacity: 0;
197
+ animation: tl-fade-in var(--transitory-label-easing) forwards;
198
+ }
199
+ .layer.outgoing.fade {
200
+ animation: tl-fade-out var(--transitory-label-easing) forwards;
201
+ }
202
+
203
+ @keyframes tl-fade-in {
204
+ from { opacity: 0; }
205
+ to { opacity: 1; }
206
+ }
207
+ @keyframes tl-fade-out {
208
+ from { opacity: 1; }
209
+ to { opacity: 0; }
210
+ }
211
+
212
+ /* character-swap */
213
+ .char {
214
+ display: inline-block;
215
+ }
216
+
217
+ .char.in {
218
+ opacity: 0;
219
+ animation: tl-char-in var(--transitory-label-easing) forwards;
220
+ }
221
+
222
+ .char.out {
223
+ animation: tl-char-out var(--transitory-label-easing) forwards;
224
+ }
225
+
226
+ @keyframes tl-char-in {
227
+ from { opacity: 0; transform: translateY(-0.3em) scale(0.8); }
228
+ to { opacity: 1; transform: translateY(0) scale(1); }
229
+ }
230
+ @keyframes tl-char-out {
231
+ from { opacity: 1; transform: translateY(0) scale(1); }
232
+ to { opacity: 0; transform: translateY(0.3em) scale(0.8); }
233
+ }
234
+ `;
235
+ }
236
+ };
237
+ __decorate([property({ type: String })], TransitoryLabelElement.prototype, "text", void 0);
238
+ __decorate([property({ type: String })], TransitoryLabelElement.prototype, "effect", void 0);
239
+ __decorate([property({ type: Number })], TransitoryLabelElement.prototype, "duration", void 0);
240
+ __decorate([property({ type: String })], TransitoryLabelElement.prototype, "easing", void 0);
241
+ __decorate([state()], TransitoryLabelElement.prototype, "_currentText", void 0);
242
+ __decorate([state()], TransitoryLabelElement.prototype, "_outgoingText", void 0);
243
+ __decorate([state()], TransitoryLabelElement.prototype, "_activeEffect", void 0);
244
+ __decorate([state()], TransitoryLabelElement.prototype, "_transitionId", void 0);
245
+ TransitoryLabelElement = __decorate([safeCustomElement(`ixfx-transitory-label`)], TransitoryLabelElement);
246
+ //#endregion
247
+ export { TransitoryLabelElement };
248
+
249
+ //# sourceMappingURL=transitory-label.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transitory-label.js","names":["#onLastCharOut","#renderCharSwap","#onOutgoingEnd","customElement"],"sources":["../src/transitory-label/transitory-label.ts"],"sourcesContent":["import type { PropertyValues } from 'lit';\nimport { css, html, LitElement, nothing } from 'lit';\nimport { property, state } from 'lit/decorators.js';\nimport { keyed } from 'lit/directives/keyed.js';\nimport { safeCustomElement as customElement } from '../util/custom-elements.js';\n\nexport type Effect = `slide-right` | `slide-left` | `slide-up` | `slide-down` | `fade` | `character-swap`;\n\ntype QueueEntry = { text: string; effect: Effect };\n\n@customElement(`ixfx-transitory-label`)\nexport class TransitoryLabelElement extends LitElement {\n @property({ type: String }) text = ``;\n @property({ type: String }) effect: Effect = `fade`;\n @property({ type: Number }) duration = 300;\n @property({ type: String }) easing = `ease`;\n\n @state() private _currentText = ``;\n @state() private _outgoingText = ``;\n @state() private _activeEffect: Effect | undefined;\n @state() private _transitionId = 0;\n\n private _queue: QueueEntry[] = [];\n private _pendingEffect: Effect | undefined;\n\n setText(msg: string, effect: Effect): void {\n this._pendingEffect = effect;\n this.text = msg;\n }\n\n protected override updated(changed: PropertyValues): void {\n if (changed.has(`text`) && this.text !== this._currentText) {\n const effect = this._pendingEffect ?? this.effect;\n this._pendingEffect = undefined;\n\n if (this._activeEffect !== undefined) {\n this._queue.push({ text: this.text, effect });\n } else {\n this._startTransition(this.text, effect);\n }\n }\n }\n\n private _startTransition(newText: string, effect: Effect): void {\n const prevText = this._currentText;\n this._currentText = newText;\n this._outgoingText = prevText;\n\n if (prevText !== ``) {\n this._transitionId++;\n this._activeEffect = effect;\n }\n }\n\n private _onTransitionEnd(): void {\n this._outgoingText = ``;\n this._activeEffect = undefined;\n\n if (this._queue.length > 0) {\n const next = this._queue.shift()!;\n this._startTransition(next.text, next.effect);\n }\n }\n\n #onOutgoingEnd = (): void => {\n this._onTransitionEnd();\n };\n\n #onLastCharOut = (): void => {\n this._onTransitionEnd();\n };\n\n #renderCharSwap() {\n const charDuration = Math.round(this.duration * 0.3);\n const charStagger = Math.round(this.duration * 0.1);\n const currentChars = this._currentText.split(``);\n const outgoingChars = this._outgoingText.split(``);\n const lastIdx = outgoingChars.length - 1;\n\n const charStyle = (i: number) =>\n `animation-duration:${charDuration}ms;animation-delay:${i * charStagger}ms;animation-timing-function:${this.easing}`;\n\n return html`\n ${keyed(`cc${this._transitionId}`, html`\n <span class=\"layer current char-swap\">\n ${currentChars.map((ch, i) => html`<span class=\"char in\" style=${charStyle(i)}>${ch}</span>`)}\n </span>\n `)}\n ${this._outgoingText\n ? keyed(this._transitionId, html`\n <span class=\"layer outgoing char-swap\">\n ${outgoingChars.map((ch, i) => html`<span\n class=\"char out\"\n style=${charStyle(i)}\n @animationend=${i === lastIdx ? this.#onLastCharOut : undefined}\n >${ch}</span>`)}\n </span>\n `)\n : nothing}\n `;\n }\n\n protected override render() {\n if (this._activeEffect === `character-swap`) {\n return html`<span class=\"container\">${this.#renderCharSwap()}</span>`;\n }\n\n const effect = this._activeEffect ?? ``;\n const durStyle = this._activeEffect\n ? `animation-duration:${this.duration}ms;animation-timing-function:${this.easing}`\n : ``;\n\n return html`\n <span class=\"container\">\n ${this._outgoingText\n ? keyed(this._transitionId, html`\n <span class=\"layer outgoing ${effect}\" style=${durStyle} @animationend=${this.#onOutgoingEnd}>\n ${this._outgoingText}\n </span>\n `)\n : nothing}\n ${keyed(`c${this._transitionId}`, html`\n <span class=\"layer current ${effect}\" style=${durStyle}>\n ${this._currentText}\n </span>\n `)}\n </span>\n `;\n }\n\n static override styles = css`\n :host {\n display: inline-block;\n --transitory-label-easing: ease;\n }\n\n .container {\n display: inline-grid;\n overflow: hidden;\n }\n\n .layer {\n grid-area: 1 / 1;\n white-space: nowrap;\n }\n\n .layer.outgoing {\n pointer-events: none;\n }\n\n /* slide-right */\n .layer.current.slide-right {\n transform: translateX(-100%);\n animation: tl-slide-in-left var(--transitory-label-easing) forwards;\n }\n .layer.outgoing.slide-right {\n animation: tl-slide-out-right var(--transitory-label-easing) forwards;\n }\n\n @keyframes tl-slide-in-left {\n from { transform: translateX(-100%); }\n to { transform: translateX(0); }\n }\n @keyframes tl-slide-out-right {\n from { transform: translateX(0); }\n to { transform: translateX(100%); }\n }\n\n /* slide-left */\n .layer.current.slide-left {\n transform: translateX(100%);\n animation: tl-slide-in-right var(--transitory-label-easing) forwards;\n }\n .layer.outgoing.slide-left {\n animation: tl-slide-out-left var(--transitory-label-easing) forwards;\n }\n\n @keyframes tl-slide-in-right {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n }\n @keyframes tl-slide-out-left {\n from { transform: translateX(0); }\n to { transform: translateX(-100%); }\n }\n\n /* slide-up */\n .layer.current.slide-up {\n transform: translateY(100%);\n animation: tl-slide-in-bottom var(--transitory-label-easing) forwards;\n }\n .layer.outgoing.slide-up {\n animation: tl-slide-out-top var(--transitory-label-easing) forwards;\n }\n\n @keyframes tl-slide-in-bottom {\n from { transform: translateY(100%); }\n to { transform: translateY(0); }\n }\n @keyframes tl-slide-out-top {\n from { transform: translateY(0); }\n to { transform: translateY(-100%); }\n }\n\n /* slide-down */\n .layer.current.slide-down {\n transform: translateY(-100%);\n animation: tl-slide-in-top var(--transitory-label-easing) forwards;\n }\n .layer.outgoing.slide-down {\n animation: tl-slide-out-bottom var(--transitory-label-easing) forwards;\n }\n\n @keyframes tl-slide-in-top {\n from { transform: translateY(-100%); }\n to { transform: translateY(0); }\n }\n @keyframes tl-slide-out-bottom {\n from { transform: translateY(0); }\n to { transform: translateY(100%); }\n }\n\n /* fade */\n .layer.current.fade {\n opacity: 0;\n animation: tl-fade-in var(--transitory-label-easing) forwards;\n }\n .layer.outgoing.fade {\n animation: tl-fade-out var(--transitory-label-easing) forwards;\n }\n\n @keyframes tl-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n @keyframes tl-fade-out {\n from { opacity: 1; }\n to { opacity: 0; }\n }\n\n /* character-swap */\n .char {\n display: inline-block;\n }\n\n .char.in {\n opacity: 0;\n animation: tl-char-in var(--transitory-label-easing) forwards;\n }\n\n .char.out {\n animation: tl-char-out var(--transitory-label-easing) forwards;\n }\n\n @keyframes tl-char-in {\n from { opacity: 0; transform: translateY(-0.3em) scale(0.8); }\n to { opacity: 1; transform: translateY(0) scale(1); }\n }\n @keyframes tl-char-out {\n from { opacity: 1; transform: translateY(0) scale(1); }\n to { opacity: 0; transform: translateY(0.3em) scale(0.8); }\n }\n `;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'ixfx-transitory-label': TransitoryLabelElement;\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { n as tickledStyles, r as TickledController, t as tickledItemStyles } from "./tickled-styles-fNDdqf6l.js";
2
- import { t as themeFallbacks } from "./fallbacks-DPgPEqo8.js";
1
+ import { t as TickledController } from "./tickled-controller-DkAU-0qL.js";
2
+ import { n as tickledStyles, t as tickledItemStyles } from "./tickled-styles-BrAHEj1q.js";
3
+ import { t as themeFallbacks } from "./fallbacks-DEE1nCTt.js";
3
4
  import { n as safeCustomElement, t as __decorate } from "./decorate-VRK8rslU.js";
4
- import "./interaction-D6efrBLo.js";
5
5
  import { t as collectDataResult } from "./data-provider-35TyWclX.js";
6
6
  import { LitElement, css, html, nothing } from "lit";
7
7
  import { property, state } from "lit/decorators.js";
@@ -1418,4 +1418,4 @@ var TreeController = class {
1418
1418
  //#endregion
1419
1419
  export { TreeDataModel as i, TreeListElement as n, TreeBaseElement as r, TreeController as t };
1420
1420
 
1421
- //# sourceMappingURL=tree-BtiiDX1a.js.map
1421
+ //# sourceMappingURL=tree-BO6BXI2b.js.map