@f-ewald/components 1.0.3 → 1.1.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 (111) hide show
  1. package/README.md +4 -1
  2. package/custom-elements.json +7 -7
  3. package/dist/address-autocomplete.d.ts.map +1 -1
  4. package/dist/address-autocomplete.js +3 -1
  5. package/dist/address-autocomplete.js.map +1 -1
  6. package/dist/autocomplete-input.d.ts.map +1 -1
  7. package/dist/autocomplete-input.js +3 -1
  8. package/dist/autocomplete-input.js.map +1 -1
  9. package/dist/calendar-month.d.ts.map +1 -1
  10. package/dist/calendar-month.js +9 -8
  11. package/dist/calendar-month.js.map +1 -1
  12. package/dist/chat-message.d.ts.map +1 -1
  13. package/dist/chat-message.js +15 -5
  14. package/dist/chat-message.js.map +1 -1
  15. package/dist/confirm-dialog.d.ts.map +1 -1
  16. package/dist/confirm-dialog.js +24 -6
  17. package/dist/confirm-dialog.js.map +1 -1
  18. package/dist/copy-link-button.d.ts.map +1 -1
  19. package/dist/copy-link-button.js +4 -2
  20. package/dist/copy-link-button.js.map +1 -1
  21. package/dist/data-table.js +1 -1
  22. package/dist/data-table.js.map +1 -1
  23. package/dist/distribution-chart.d.ts +2 -2
  24. package/dist/distribution-chart.js +4 -4
  25. package/dist/distribution-chart.js.map +1 -1
  26. package/dist/dropdown-button.d.ts.map +1 -1
  27. package/dist/dropdown-button.js +13 -2
  28. package/dist/dropdown-button.js.map +1 -1
  29. package/dist/form-select.d.ts.map +1 -1
  30. package/dist/form-select.js +32 -8
  31. package/dist/form-select.js.map +1 -1
  32. package/dist/frame-box.js +3 -3
  33. package/dist/frame-box.js.map +1 -1
  34. package/dist/icon-button.d.ts +1 -1
  35. package/dist/icon-button.js +1 -1
  36. package/dist/icon-button.js.map +1 -1
  37. package/dist/kbd-hint.js +1 -1
  38. package/dist/kbd-hint.js.map +1 -1
  39. package/dist/map-circle.js +2 -2
  40. package/dist/map-circle.js.map +1 -1
  41. package/dist/map-pin.js +2 -2
  42. package/dist/map-pin.js.map +1 -1
  43. package/dist/percent-bar-chart.js +1 -1
  44. package/dist/percent-bar-chart.js.map +1 -1
  45. package/dist/photo-gallery.d.ts.map +1 -1
  46. package/dist/photo-gallery.js +33 -9
  47. package/dist/photo-gallery.js.map +1 -1
  48. package/dist/popover-panel.d.ts.map +1 -1
  49. package/dist/popover-panel.js +7 -4
  50. package/dist/popover-panel.js.map +1 -1
  51. package/dist/radio-cards.d.ts.map +1 -1
  52. package/dist/radio-cards.js +4 -3
  53. package/dist/radio-cards.js.map +1 -1
  54. package/dist/radio-pills.d.ts.map +1 -1
  55. package/dist/radio-pills.js +7 -4
  56. package/dist/radio-pills.js.map +1 -1
  57. package/dist/reveal-button.d.ts.map +1 -1
  58. package/dist/reveal-button.js +4 -1
  59. package/dist/reveal-button.js.map +1 -1
  60. package/dist/slide-panel.d.ts.map +1 -1
  61. package/dist/slide-panel.js +8 -5
  62. package/dist/slide-panel.js.map +1 -1
  63. package/dist/stat-meter.js +3 -3
  64. package/dist/stat-meter.js.map +1 -1
  65. package/dist/status-pill.js +2 -2
  66. package/dist/status-pill.js.map +1 -1
  67. package/dist/tile-grid.js +1 -1
  68. package/dist/tile-grid.js.map +1 -1
  69. package/dist/toast-notification.d.ts.map +1 -1
  70. package/dist/toast-notification.js +10 -5
  71. package/dist/toast-notification.js.map +1 -1
  72. package/dist/tokens.css +10 -0
  73. package/dist/tokens.d.ts.map +1 -1
  74. package/dist/tokens.js +15 -2
  75. package/dist/tokens.js.map +1 -1
  76. package/dist/ui-button.d.ts.map +1 -1
  77. package/dist/ui-button.js +3 -1
  78. package/dist/ui-button.js.map +1 -1
  79. package/dist/user-avatar.js +1 -1
  80. package/dist/user-avatar.js.map +1 -1
  81. package/dist/weight-bar-chart.js +2 -2
  82. package/dist/weight-bar-chart.js.map +1 -1
  83. package/docs/address-autocomplete.md +1 -0
  84. package/docs/autocomplete-input.md +1 -0
  85. package/docs/calendar-month.md +6 -1
  86. package/docs/chat-message.md +2 -0
  87. package/docs/confirm-dialog.md +3 -0
  88. package/docs/data-table.md +1 -0
  89. package/docs/design-language.md +68 -40
  90. package/docs/distribution-chart.md +3 -2
  91. package/docs/dropdown-button.md +2 -0
  92. package/docs/form-select.md +2 -0
  93. package/docs/frame-box.md +3 -1
  94. package/docs/icon-button.md +1 -1
  95. package/docs/kbd-hint.md +1 -0
  96. package/docs/map-circle.md +2 -0
  97. package/docs/map-pin.md +2 -0
  98. package/docs/photo-gallery.md +1 -0
  99. package/docs/popover-panel.md +3 -1
  100. package/docs/radio-cards.md +2 -0
  101. package/docs/radio-pills.md +1 -0
  102. package/docs/reveal-button.md +3 -1
  103. package/docs/slide-panel.md +3 -1
  104. package/docs/stat-meter.md +3 -0
  105. package/docs/status-pill.md +1 -0
  106. package/docs/toast-notification.md +2 -0
  107. package/docs/ui-button.md +2 -0
  108. package/docs/user-avatar.md +1 -0
  109. package/docs/weight-bar-chart.md +0 -1
  110. package/llms.txt +27 -27
  111. package/package.json +1 -3
package/README.md CHANGED
@@ -128,6 +128,10 @@ value instead of the inherited one, silently discarding whatever `:root`
128
128
  set. Don't reintroduce that pattern.)
129
129
 
130
130
  The full token set is defined in [`src/tokens.ts`](./src/tokens.ts).
131
+ Typography, spacing, control, icon, radius, panel, chart, and accessibility
132
+ measurements follow the canonical
133
+ [`docs/design-language.md`](./docs/design-language.md) contract and are checked
134
+ by `npm run test:design`.
131
135
 
132
136
  ## MCP server
133
137
 
@@ -199,7 +203,6 @@ requests.
199
203
  | `npm run mcp` | Run the MCP server (`dist/mcp-server.js`) directly, for manual testing. |
200
204
  | `npm run test` | Run the Playwright suite against the playground. |
201
205
  | `npm run test:design` | Check catalog ordering, token fallbacks, and source design contracts. |
202
- | `npm run test:visual` | Compare light/dark component screenshots. |
203
206
  | `npm run test:site` | Run the Playwright smoke suite against `pages-dist/`. |
204
207
 
205
208
  ## Contributing
@@ -2858,7 +2858,7 @@
2858
2858
  "declarations": [
2859
2859
  {
2860
2860
  "kind": "class",
2861
- "description": "Renders a KDE distribution curve for a named metric with one or more value\nmarkers. The SVG viewBox is kept in sync with the element's pixel width via\nResizeObserver so that font sizes and stroke widths are always in real pixels\nregardless of container width.\n\nPass `fontSize` to control all text size (default 11). Pass a single\n`{label:'', value}` for a single-value display or multiple\n`{label:'A'|'B'|...}` entries to compare several values.",
2861
+ "description": "Renders a KDE distribution curve for a named metric with one or more value\nmarkers. The SVG viewBox is kept in sync with the element's pixel width via\nResizeObserver so that font sizes and stroke widths are always in real pixels\nregardless of container width.\n\nPass `fontSize` to control all text size (default 10). Pass a single\n`{label:'', value}` for a single-value display or multiple\n`{label:'A'|'B'|...}` entries to compare several values.",
2862
2862
  "name": "DistributionChart",
2863
2863
  "members": [
2864
2864
  {
@@ -2895,8 +2895,8 @@
2895
2895
  "type": {
2896
2896
  "text": "number"
2897
2897
  },
2898
- "default": "11",
2899
- "description": "Target font size in CSS pixels (default 11). Always renders at this size regardless of container width.",
2898
+ "default": "10",
2899
+ "description": "Target font size in CSS pixels (default 10). Always renders at this size regardless of container width.",
2900
2900
  "attribute": "font-size"
2901
2901
  },
2902
2902
  {
@@ -3011,8 +3011,8 @@
3011
3011
  "type": {
3012
3012
  "text": "number"
3013
3013
  },
3014
- "default": "11",
3015
- "description": "Target font size in CSS pixels (default 11). Always renders at this size regardless of container width.",
3014
+ "default": "10",
3015
+ "description": "Target font size in CSS pixels (default 10). Always renders at this size regardless of container width.",
3016
3016
  "fieldName": "fontSize"
3017
3017
  }
3018
3018
  ],
@@ -4366,7 +4366,7 @@
4366
4366
  "text": "TemplateResult | null"
4367
4367
  },
4368
4368
  "default": "null",
4369
- "description": "Pre-rendered icon template, e.g. `iconPencil(16)` from this package's icon set."
4369
+ "description": "Pre-rendered icon template, e.g. `iconPencil(18)` from this package's icon set."
4370
4370
  },
4371
4371
  {
4372
4372
  "kind": "field",
@@ -8388,7 +8388,7 @@
8388
8388
  "type": {
8389
8389
  "text": "Record<string, string>"
8390
8390
  },
8391
- "default": "{ // Colors \"--ui-primary\": \"#4f46e5\", // indigo-600 \"--ui-primary-hover\": \"#4338ca\", // indigo-700 \"--ui-info\": \"#0ea5e9\", // sky-500 \"--ui-info-hover\": \"#0284c7\", // sky-600 \"--ui-danger\": \"#dc2626\", // red-600 \"--ui-danger-hover\": \"#b91c1c\", // red-700 \"--ui-success\": \"#16a34a\", // green-600 \"--ui-warning\": \"#d97706\", // amber-600 \"--ui-warning-hover\": \"#b45309\", // amber-700 \"--ui-on-accent\": \"#ffffff\", \"--ui-text\": \"#0f172a\", // slate-900 \"--ui-text-muted\": \"#64748b\", // slate-500 \"--ui-border\": \"#e2e8f0\", // slate-200 \"--ui-surface\": \"#ffffff\", // white \"--ui-surface-muted\": \"#f8fafc\", // slate-50 \"--ui-tooltip\": \"#0f172a\", // slate-900 \"--ui-hover-overlay\": \"rgb(255 255 255 / 0.32)\", \"--ui-overlay\": \"rgb(15 23 42 / 0.45)\", // slate-900 / 45% // Shape / depth \"--ui-radius\": \"0.5rem\", // rounded-lg \"--ui-radius-sm\": \"0.25rem\", // rounded \"--ui-shadow\": \"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)\", // shadow-md \"--ui-shadow-lg\": \"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)\", // shadow-xl \"--ui-focus-ring\": \"0 0 0 3px rgb(79 70 229 / 0.35)\", // Type \"--ui-font\": 'ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\"', \"--ui-font-mono\": \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\", \"--ui-font-size\": \"0.875rem\", \"--ui-font-size-sm\": \"0.75rem\", \"--ui-font-size-xs\": \"0.6875rem\", }",
8391
+ "default": "{ // Colors \"--ui-primary\": \"#4f46e5\", // indigo-600 \"--ui-primary-hover\": \"#4338ca\", // indigo-700 \"--ui-info\": \"#0ea5e9\", // sky-500 \"--ui-info-hover\": \"#0284c7\", // sky-600 \"--ui-danger\": \"#dc2626\", // red-600 \"--ui-danger-hover\": \"#b91c1c\", // red-700 \"--ui-success\": \"#16a34a\", // green-600 \"--ui-warning\": \"#d97706\", // amber-600 \"--ui-warning-hover\": \"#b45309\", // amber-700 \"--ui-on-accent\": \"#ffffff\", \"--ui-text\": \"#0f172a\", // slate-900 \"--ui-text-muted\": \"#64748b\", // slate-500 \"--ui-border\": \"#e2e8f0\", // slate-200 \"--ui-surface\": \"#ffffff\", // white \"--ui-surface-muted\": \"#f8fafc\", // slate-50 \"--ui-tooltip\": \"#0f172a\", // slate-900 \"--ui-hover-overlay\": \"rgb(255 255 255 / 0.32)\", \"--ui-overlay\": \"rgb(15 23 42 / 0.45)\", // slate-900 / 45% // Shape / depth \"--ui-radius\": \"0.5rem\", // rounded-lg \"--ui-radius-sm\": \"0.25rem\", // rounded \"--ui-shadow\": \"0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)\", // shadow-md \"--ui-shadow-lg\": \"0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1)\", // shadow-xl \"--ui-focus-ring\": \"0 0 0 3px rgb(79 70 229 / 0.35)\", // Type \"--ui-font\": 'ui-sans-serif, system-ui, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\", \"Noto Color Emoji\"', \"--ui-font-mono\": \"ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace\", \"--ui-font-size-lg\": \"1rem\", // text-base \"--ui-font-size\": \"0.875rem\", // text-sm \"--ui-font-size-sm\": \"0.75rem\", // text-xs \"--ui-font-size-xs\": \"0.6875rem\", // Font weights — the only four weights the system uses. \"--ui-font-weight-regular\": \"400\", \"--ui-font-weight-medium\": \"500\", \"--ui-font-weight-semibold\": \"600\", \"--ui-font-weight-bold\": \"700\", // Line heights — glyph (icon/marker box), tight (headings), normal (body). \"--ui-line-height-glyph\": \"1\", \"--ui-line-height-tight\": \"1.25\", \"--ui-line-height-normal\": \"1.5\", // Letter spacing / tracking — default and the single widened step. \"--ui-tracking-normal\": \"0\", \"--ui-tracking-wide\": \"0.04em\", }",
8392
8392
  "description": "Design token values, sourced from Tailwind v4's default theme palette.\nEach entry maps a `--ui-*` custom property name to its default value.\nThese are the same values baked in as `var(--ui-*, <fallback>)` fallbacks\nthroughout component styles, so components render correctly with zero\nexternal CSS. Consumers may override any of these by setting the custom\nproperty on `:root` or an ancestor element (see `tokens.css`)."
8393
8393
  },
8394
8394
  {
@@ -1 +1 @@
1
- {"version":3,"file":"address-autocomplete.d.ts","sourceRoot":"","sources":["../src/address-autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAO1E,mCAAmC;AACnC,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAOD;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,mBAAoB,SAAQ,UAAU;;IACjD,MAAM,CAAC,cAAc,UAAQ;IAE7B,OAAgB,MAAM,4BAoFpB;IAEF,mFAAmF;IACvE,KAAK,SAAM;IACvB,sDAAsD;IAC1C,WAAW,SAAM;IAC7B,8DAA8D;IACjC,QAAQ,UAAS;IAC9C,0DAA0D;IACd,QAAQ,UAAS;IAC7D,6DAA6D;IACjD,KAAK,SAAa;IAC9B,+EAA+E;IACnE,QAAQ,EAAE,MAAM,CAAsD;IAClF,6DAA6D;IACpB,WAAW,SAAM;IAC1D,2EAA2E;IAC/D,IAAI,SAAM;IACtB,0DAA0D;IAC9C,SAAS,SAAM;IAC3B,wEAAwE;IAC5C,QAAQ,SAAO;IAC3C,2DAA2D;IACN,SAAS,SAAK;IACnE;;;;OAIG;IAC6B,WAAW,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAQ;IAEtE,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAS;IAgBvC,uEAAuE;IACvE,IAAI,kBAAkB,IAAI,iBAAiB,GAAG,IAAI,CAGjD;IAED,UAAmB,UAAU,CAAC,OAAO,EAAE,cAAc,QAQpD;IAED,UAAmB,OAAO,CAAC,OAAO,EAAE,cAAc,QAEjD;IAEQ,oBAAoB,SAK5B;IAED,0FAA0F;IAC1F,iBAAiB,SAKhB;IAED,sEAAsE;IACtE,oBAAoB,CAAC,QAAQ,EAAE,OAAO,QAQrC;IAED,OAAO,CAAC,OAAO;IAuEf,OAAO,CAAC,SAAS;IAuCjB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,iBAAiB;IA0BhB,MAAM,yCA6Bd;CACF;AAcD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,sBAAsB,EAAE,mBAAmB,CAAC;KAC7C;CACF"}
1
+ {"version":3,"file":"address-autocomplete.d.ts","sourceRoot":"","sources":["../src/address-autocomplete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAO1E,mCAAmC;AACnC,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAOD;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,mBAAoB,SAAQ,UAAU;;IACjD,MAAM,CAAC,cAAc,UAAQ;IAE7B,OAAgB,MAAM,4BAsFpB;IAEF,mFAAmF;IACvE,KAAK,SAAM;IACvB,sDAAsD;IAC1C,WAAW,SAAM;IAC7B,8DAA8D;IACjC,QAAQ,UAAS;IAC9C,0DAA0D;IACd,QAAQ,UAAS;IAC7D,6DAA6D;IACjD,KAAK,SAAa;IAC9B,+EAA+E;IACnE,QAAQ,EAAE,MAAM,CAAsD;IAClF,6DAA6D;IACpB,WAAW,SAAM;IAC1D,2EAA2E;IAC/D,IAAI,SAAM;IACtB,0DAA0D;IAC9C,SAAS,SAAM;IAC3B,wEAAwE;IAC5C,QAAQ,SAAO;IAC3C,2DAA2D;IACN,SAAS,SAAK;IACnE;;;;OAIG;IAC6B,WAAW,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAQ;IAEtE,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAS;IAgBvC,uEAAuE;IACvE,IAAI,kBAAkB,IAAI,iBAAiB,GAAG,IAAI,CAGjD;IAED,UAAmB,UAAU,CAAC,OAAO,EAAE,cAAc,QAQpD;IAED,UAAmB,OAAO,CAAC,OAAO,EAAE,cAAc,QAEjD;IAEQ,oBAAoB,SAK5B;IAED,0FAA0F;IAC1F,iBAAiB,SAKhB;IAED,sEAAsE;IACtE,oBAAoB,CAAC,QAAQ,EAAE,OAAO,QAQrC;IAED,OAAO,CAAC,OAAO;IAuEf,OAAO,CAAC,SAAS;IAuCjB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,iBAAiB;IA0BhB,MAAM,yCA6Bd;CACF;AAcD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,sBAAsB,EAAE,mBAAmB,CAAC;KAC7C;CACF"}
@@ -90,12 +90,14 @@ let AddressAutocomplete = class AddressAutocomplete extends LitElement {
90
90
  "Noto Color Emoji"
91
91
  );
92
92
  font-size: var(--ui-font-size-sm, 0.75rem);
93
+ line-height: var(--ui-line-height-tight, 1.25);
93
94
  color: var(--ui-text, #0f172a);
94
95
  background: var(--ui-surface, #ffffff);
95
- padding: 0.5rem;
96
+ padding: 0.5rem 0.75rem;
96
97
  border: 1px solid var(--ui-border, #e2e8f0);
97
98
  border-radius: var(--ui-radius-sm, 0.25rem);
98
99
  width: 100%;
100
+ height: 2rem;
99
101
  box-sizing: border-box;
100
102
  }
101
103
  input:disabled {
@@ -1 +1 @@
1
- {"version":3,"file":"address-autocomplete.js","sourceRoot":"","sources":["../src/address-autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing, type PropertyValues } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\nimport { submitWithDefaultButton } from \"./utils/form.js\";\n\nlet instanceCount = 0;\n\n/** A picked address suggestion. */\nexport interface AddressSuggestion {\n address: string;\n lat: number;\n lng: number;\n}\n\ninterface MapboxGeocodeFeature {\n properties?: { full_address?: string };\n geometry: { coordinates: [number, number] };\n}\n\n/**\n * Form-associated text input with a suggestion dropdown. Works as a\n * drop-in replacement for a plain `<input name=\"address\">`: consumers keep\n * reading `new FormData(form).get(\"address\")` and calling `form.reset()`\n * unchanged.\n *\n * Supports two suggestion sources:\n * - **API** (default): fetches from `endpoint`, a Mapbox Geocoding v6-shaped\n * forward-geocode URL, debounced as the user types.\n * - **Local array**: set `suggestions` to a fixed `AddressSuggestion[]` and\n * the component filters it client-side instead of making any network\n * request. Useful for small/fixed address lists, offline use, or tests.\n * Takes priority over `endpoint` whenever it's non-null.\n *\n * @element address-autocomplete\n * @fires address-select - A suggestion was picked; detail: AddressSuggestion.\n */\n@customElement(\"address-autocomplete\")\nexport class AddressAutocomplete extends LitElement {\n static formAssociated = true;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n position: relative;\n }\n input {\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size-sm, 0.75rem);\n color: var(--ui-text, #0f172a);\n background: var(--ui-surface, #ffffff);\n padding: 0.5rem;\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n width: 100%;\n box-sizing: border-box;\n }\n input:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n }\n input:focus-visible {\n outline: none;\n border-color: var(--ui-primary, #4f46e5);\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n .suggestions {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: 10;\n max-height: 40vh;\n overflow-y: auto;\n margin: 0.25rem 0 0;\n padding: 0.25rem 0;\n list-style: none;\n background: var(--ui-surface, #ffffff);\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n box-shadow: var(--ui-shadow, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1));\n }\n .suggestion {\n padding: 0.5rem 0.75rem;\n font-size: var(--ui-font-size-sm, 0.75rem);\n cursor: pointer;\n }\n .suggestion.active,\n .suggestion:hover {\n background: var(--ui-surface-muted, #f8fafc);\n }\n .no-suggestions {\n padding: 0.5rem 0.75rem;\n color: var(--ui-text-muted, #64748b);\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-style: italic;\n }\n @media (forced-colors: active) {\n input:focus-visible {\n outline: 2px solid CanvasText;\n outline-offset: 2px;\n box-shadow: none;\n }\n input:disabled {\n color: GrayText;\n opacity: 1;\n }\n .suggestion.active,\n .suggestion:hover {\n color: HighlightText;\n background: Highlight;\n }\n }\n `,\n ];\n\n /** Current input value; also the form-associated value submitted with the form. */\n @property() value = \"\";\n /** Placeholder text shown when the input is empty. */\n @property() placeholder = \"\";\n /** Marks the input as required for native form validation. */\n @property({ type: Boolean }) required = false;\n /** Disables the input and closes its suggestion popup. */\n @property({ type: Boolean, reflect: true }) disabled = false;\n /** Mapbox `types` param, e.g. \"address\" or \"address,poi\". */\n @property() types = \"address\";\n /** Geocoding endpoint URL. Defaults to the Mapbox Geocoding v6 forward URL. */\n @property() endpoint: string = \"https://api.mapbox.com/search/geocode/v6/forward\";\n /** Mapbox access token. Required for requests to succeed. */\n @property({ attribute: \"access-token\" }) accessToken = \"\";\n /** Optional bounding box bias, comma-separated `west,south,east,north`. */\n @property() bbox = \"\";\n /** Optional proximity bias, comma-separated `lng,lat`. */\n @property() proximity = \"\";\n /** Debounce delay (ms) before firing a geocode request after typing. */\n @property({ type: Number }) debounce = 300;\n /** Minimum query length before suggestions are fetched. */\n @property({ type: Number, attribute: \"min-length\" }) minLength = 3;\n /**\n * Fixed candidate list to filter locally instead of fetching from\n * `endpoint`. When set (non-null), no network request is ever made —\n * this takes priority over the API mode.\n */\n @property({ attribute: false }) suggestions: AddressSuggestion[] | null = null;\n\n @state() private _suggestions: AddressSuggestion[] = [];\n @state() private _open = false;\n @state() private _activeIndex = -1;\n @state() private _formDisabled = false;\n\n #internals = this.attachInternals();\n #lastPicked: AddressSuggestion | null = null;\n #debounceTimer: ReturnType<typeof setTimeout> | null = null;\n #abortController: AbortController | null = null;\n #isComposing = false;\n #compositionJustEnded = false;\n #compositionEndTimer: ReturnType<typeof setTimeout> | null = null;\n readonly #listboxId = `address-autocomplete-listbox-${++instanceCount}`;\n\n /** Whether the host or an ancestor fieldset currently disables the control. */\n get #isDisabled(): boolean {\n return this.disabled || this._formDisabled;\n }\n\n /** Last-picked suggestion, or null once the input diverges from it. */\n get selectedSuggestion(): AddressSuggestion | null {\n if (this.#lastPicked && this.#lastPicked.address === this.value) return this.#lastPicked;\n return null;\n }\n\n protected override willUpdate(changed: PropertyValues) {\n if (changed.has(\"disabled\") && this.#isDisabled) {\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n this._open = false;\n this._activeIndex = -1;\n }\n }\n\n protected override updated(changed: PropertyValues) {\n if (changed.has(\"value\")) this.#internals.setFormValue(this.value);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n }\n\n /** Resets to empty on `form.reset()`, per the form-associated custom element contract. */\n formResetCallback() {\n this.value = \"\";\n this._suggestions = [];\n this._open = false;\n this.#lastPicked = null;\n }\n\n /** Mirrors ancestor fieldset disabled state onto the native input. */\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled;\n if (!disabled) return;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n this._open = false;\n this._activeIndex = -1;\n }\n\n private onInput(e: InputEvent) {\n if (this.#isDisabled) return;\n this.value = (e.target as HTMLInputElement).value;\n this.#lastPicked = null;\n this.#scheduleFetch(this.value);\n }\n\n #scheduleFetch(query: string) {\n if (this.#isDisabled) return;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n if (query.trim().length < this.minLength) {\n this._suggestions = [];\n this._open = false;\n this._activeIndex = -1;\n return;\n }\n if (this.suggestions) {\n // Local mode: filtering is synchronous and cheap, but keep the same\n // debounce as the API mode so the UX doesn't shift between sources.\n this.#debounceTimer = setTimeout(() => this.#filterLocalSuggestions(query), this.debounce);\n return;\n }\n this.#debounceTimer = setTimeout(() => void this.#fetchSuggestions(query), this.debounce);\n }\n\n /** Filters the locally-supplied `suggestions` list for `query`, case-insensitively. */\n #filterLocalSuggestions(query: string) {\n const needle = query.trim().toLowerCase();\n this._suggestions = (this.suggestions ?? [])\n .filter((s) => s.address.toLowerCase().includes(needle))\n .slice(0, 5);\n this._activeIndex = -1;\n this._open = !this.#isDisabled;\n }\n\n /** Fetches suggestions for `query`, cancelling any request still in flight. */\n async #fetchSuggestions(query: string) {\n this.#abortController?.abort();\n const controller = new AbortController();\n this.#abortController = controller;\n try {\n const res = await fetch(this.#buildUrl(query), { signal: controller.signal });\n if (!res.ok) throw new Error(`geocode request failed: ${res.status}`);\n const body = (await res.json()) as { features?: MapboxGeocodeFeature[] };\n if (this.#isDisabled) return;\n this._suggestions = parseFeatures(body.features ?? []);\n this._activeIndex = -1;\n this._open = true;\n } catch {\n // Aborted (superseded by newer keystroke) or a network failure while\n // typing — fail silently and just close the list.\n if (!controller.signal.aborted) {\n this._suggestions = [];\n this._open = false;\n }\n }\n }\n\n #buildUrl(query: string): string {\n const params = new URLSearchParams({\n q: query,\n access_token: this.accessToken,\n autocomplete: \"true\",\n limit: \"5\",\n types: this.types,\n });\n if (this.bbox) params.set(\"bbox\", this.bbox);\n if (this.proximity) params.set(\"proximity\", this.proximity);\n return `${this.endpoint}?${params.toString()}`;\n }\n\n private onKeydown(e: KeyboardEvent) {\n if (this.#isDisabled) return;\n if (e.isComposing || e.keyCode === 229 || this.#isComposing || this.#compositionJustEnded) {\n return;\n }\n if (e.key === \"ArrowDown\") this.#moveActive(1, e);\n else if (e.key === \"ArrowUp\") this.#moveActive(-1, e);\n else if (e.key === \"Enter\") this.#handleEnter(e);\n else if (e.key === \"Escape\") this.#handleEscape(e);\n }\n\n #moveActive(delta: number, e: KeyboardEvent) {\n if (!this._open || this._suggestions.length === 0) return;\n e.preventDefault();\n const n = this._suggestions.length;\n this._activeIndex = (this._activeIndex + delta + n) % n;\n }\n\n #handleEnter(e: KeyboardEvent) {\n const pick = this._suggestions[this._activeIndex] ?? this._suggestions[0];\n if (this._open && pick) {\n e.preventDefault();\n this.#selectSuggestion(pick);\n return;\n }\n if (this.#internals.form) {\n const form = this.#internals.form;\n window.setTimeout(() => {\n if (!e.defaultPrevented && form.isConnected) submitWithDefaultButton(form);\n });\n }\n }\n\n #handleEscape(e: KeyboardEvent) {\n if (!this._open) return;\n e.preventDefault();\n this._open = false;\n }\n\n private onBlur() {\n this._open = false;\n }\n\n private onCompositionStart(): void {\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = null;\n this.#compositionJustEnded = false;\n this.#isComposing = true;\n }\n\n private onCompositionEnd(): void {\n this.#isComposing = false;\n this.#compositionJustEnded = true;\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = setTimeout(() => {\n this.#compositionJustEnded = false;\n this.#compositionEndTimer = null;\n });\n }\n\n /** Clears composition state when the control can no longer receive keys. */\n #resetComposition(): void {\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = null;\n this.#isComposing = false;\n this.#compositionJustEnded = false;\n }\n\n #selectSuggestion(s: AddressSuggestion) {\n this.value = s.address;\n this.#lastPicked = s;\n this._open = false;\n this._suggestions = [];\n this.dispatchEvent(new CustomEvent<AddressSuggestion>(\"address-select\", { detail: s, bubbles: true, composed: true }));\n }\n\n /** Selects on mousedown (not click) so it wins over the input's blur, which closes the list. */\n #onSuggestionMousedown(e: MouseEvent, s: AddressSuggestion) {\n e.preventDefault();\n this.#selectSuggestion(s);\n }\n\n private renderSuggestions() {\n if (!this._open || this.#isDisabled) return nothing;\n return html`\n <ul id=${this.#listboxId} class=\"suggestions\" role=\"listbox\" aria-label=\"Address suggestions\">\n ${this._suggestions.map(\n (s, i) => html`\n <li\n id=${`${this.#listboxId}-option-${i}`}\n role=\"option\"\n aria-selected=${i === this._activeIndex}\n class=\"suggestion ${i === this._activeIndex ? \"active\" : \"\"}\"\n @mousedown=${(e: MouseEvent) => this.#onSuggestionMousedown(e, s)}\n >\n ${s.address}\n </li>\n `,\n )}\n ${this._suggestions.length === 0\n ? html`<li class=\"no-suggestions\" role=\"presentation\">\n <span role=\"status\">No suggestions found</span>\n </li>`\n : nothing}\n </ul>\n `;\n }\n\n override render() {\n const activeDescendant =\n this._open && !this.#isDisabled && this._activeIndex >= 0\n ? `${this.#listboxId}-option-${this._activeIndex}`\n : nothing;\n const expanded = this._open && !this.#isDisabled;\n return html`\n <div>\n <input\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=${expanded}\n aria-controls=${this.#listboxId}\n aria-activedescendant=${activeDescendant}\n .value=${this.value}\n placeholder=${this.placeholder}\n ?required=${this.required}\n ?disabled=${this.#isDisabled}\n autocomplete=\"off\"\n @input=${this.onInput}\n @compositionstart=${this.onCompositionStart}\n @compositionend=${this.onCompositionEnd}\n @keydown=${this.onKeydown}\n @blur=${this.onBlur}\n />\n ${this.renderSuggestions()}\n </div>\n `;\n }\n}\n\n/** Maps Mapbox v6 forward-geocode features to suggestions, skipping ones without a full_address. */\nfunction parseFeatures(features: MapboxGeocodeFeature[]): AddressSuggestion[] {\n const suggestions: AddressSuggestion[] = [];\n for (const f of features) {\n const address = f.properties?.full_address;\n if (!address) continue;\n const [lng, lat] = f.geometry.coordinates;\n suggestions.push({ address, lng, lat });\n }\n return suggestions;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"address-autocomplete\": AddressAutocomplete;\n }\n}\n"]}
1
+ {"version":3,"file":"address-autocomplete.js","sourceRoot":"","sources":["../src/address-autocomplete.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing, type PropertyValues } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\nimport { submitWithDefaultButton } from \"./utils/form.js\";\n\nlet instanceCount = 0;\n\n/** A picked address suggestion. */\nexport interface AddressSuggestion {\n address: string;\n lat: number;\n lng: number;\n}\n\ninterface MapboxGeocodeFeature {\n properties?: { full_address?: string };\n geometry: { coordinates: [number, number] };\n}\n\n/**\n * Form-associated text input with a suggestion dropdown. Works as a\n * drop-in replacement for a plain `<input name=\"address\">`: consumers keep\n * reading `new FormData(form).get(\"address\")` and calling `form.reset()`\n * unchanged.\n *\n * Supports two suggestion sources:\n * - **API** (default): fetches from `endpoint`, a Mapbox Geocoding v6-shaped\n * forward-geocode URL, debounced as the user types.\n * - **Local array**: set `suggestions` to a fixed `AddressSuggestion[]` and\n * the component filters it client-side instead of making any network\n * request. Useful for small/fixed address lists, offline use, or tests.\n * Takes priority over `endpoint` whenever it's non-null.\n *\n * @element address-autocomplete\n * @fires address-select - A suggestion was picked; detail: AddressSuggestion.\n */\n@customElement(\"address-autocomplete\")\nexport class AddressAutocomplete extends LitElement {\n static formAssociated = true;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n position: relative;\n }\n input {\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size-sm, 0.75rem);\n line-height: var(--ui-line-height-tight, 1.25);\n color: var(--ui-text, #0f172a);\n background: var(--ui-surface, #ffffff);\n padding: 0.5rem 0.75rem;\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n width: 100%;\n height: 2rem;\n box-sizing: border-box;\n }\n input:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n }\n input:focus-visible {\n outline: none;\n border-color: var(--ui-primary, #4f46e5);\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n .suggestions {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: 10;\n max-height: 40vh;\n overflow-y: auto;\n margin: 0.25rem 0 0;\n padding: 0.25rem 0;\n list-style: none;\n background: var(--ui-surface, #ffffff);\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n box-shadow: var(--ui-shadow, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1));\n }\n .suggestion {\n padding: 0.5rem 0.75rem;\n font-size: var(--ui-font-size-sm, 0.75rem);\n cursor: pointer;\n }\n .suggestion.active,\n .suggestion:hover {\n background: var(--ui-surface-muted, #f8fafc);\n }\n .no-suggestions {\n padding: 0.5rem 0.75rem;\n color: var(--ui-text-muted, #64748b);\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-style: italic;\n }\n @media (forced-colors: active) {\n input:focus-visible {\n outline: 2px solid CanvasText;\n outline-offset: 2px;\n box-shadow: none;\n }\n input:disabled {\n color: GrayText;\n opacity: 1;\n }\n .suggestion.active,\n .suggestion:hover {\n color: HighlightText;\n background: Highlight;\n }\n }\n `,\n ];\n\n /** Current input value; also the form-associated value submitted with the form. */\n @property() value = \"\";\n /** Placeholder text shown when the input is empty. */\n @property() placeholder = \"\";\n /** Marks the input as required for native form validation. */\n @property({ type: Boolean }) required = false;\n /** Disables the input and closes its suggestion popup. */\n @property({ type: Boolean, reflect: true }) disabled = false;\n /** Mapbox `types` param, e.g. \"address\" or \"address,poi\". */\n @property() types = \"address\";\n /** Geocoding endpoint URL. Defaults to the Mapbox Geocoding v6 forward URL. */\n @property() endpoint: string = \"https://api.mapbox.com/search/geocode/v6/forward\";\n /** Mapbox access token. Required for requests to succeed. */\n @property({ attribute: \"access-token\" }) accessToken = \"\";\n /** Optional bounding box bias, comma-separated `west,south,east,north`. */\n @property() bbox = \"\";\n /** Optional proximity bias, comma-separated `lng,lat`. */\n @property() proximity = \"\";\n /** Debounce delay (ms) before firing a geocode request after typing. */\n @property({ type: Number }) debounce = 300;\n /** Minimum query length before suggestions are fetched. */\n @property({ type: Number, attribute: \"min-length\" }) minLength = 3;\n /**\n * Fixed candidate list to filter locally instead of fetching from\n * `endpoint`. When set (non-null), no network request is ever made —\n * this takes priority over the API mode.\n */\n @property({ attribute: false }) suggestions: AddressSuggestion[] | null = null;\n\n @state() private _suggestions: AddressSuggestion[] = [];\n @state() private _open = false;\n @state() private _activeIndex = -1;\n @state() private _formDisabled = false;\n\n #internals = this.attachInternals();\n #lastPicked: AddressSuggestion | null = null;\n #debounceTimer: ReturnType<typeof setTimeout> | null = null;\n #abortController: AbortController | null = null;\n #isComposing = false;\n #compositionJustEnded = false;\n #compositionEndTimer: ReturnType<typeof setTimeout> | null = null;\n readonly #listboxId = `address-autocomplete-listbox-${++instanceCount}`;\n\n /** Whether the host or an ancestor fieldset currently disables the control. */\n get #isDisabled(): boolean {\n return this.disabled || this._formDisabled;\n }\n\n /** Last-picked suggestion, or null once the input diverges from it. */\n get selectedSuggestion(): AddressSuggestion | null {\n if (this.#lastPicked && this.#lastPicked.address === this.value) return this.#lastPicked;\n return null;\n }\n\n protected override willUpdate(changed: PropertyValues) {\n if (changed.has(\"disabled\") && this.#isDisabled) {\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n this._open = false;\n this._activeIndex = -1;\n }\n }\n\n protected override updated(changed: PropertyValues) {\n if (changed.has(\"value\")) this.#internals.setFormValue(this.value);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n }\n\n /** Resets to empty on `form.reset()`, per the form-associated custom element contract. */\n formResetCallback() {\n this.value = \"\";\n this._suggestions = [];\n this._open = false;\n this.#lastPicked = null;\n }\n\n /** Mirrors ancestor fieldset disabled state onto the native input. */\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled;\n if (!disabled) return;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n this._open = false;\n this._activeIndex = -1;\n }\n\n private onInput(e: InputEvent) {\n if (this.#isDisabled) return;\n this.value = (e.target as HTMLInputElement).value;\n this.#lastPicked = null;\n this.#scheduleFetch(this.value);\n }\n\n #scheduleFetch(query: string) {\n if (this.#isDisabled) return;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n if (query.trim().length < this.minLength) {\n this._suggestions = [];\n this._open = false;\n this._activeIndex = -1;\n return;\n }\n if (this.suggestions) {\n // Local mode: filtering is synchronous and cheap, but keep the same\n // debounce as the API mode so the UX doesn't shift between sources.\n this.#debounceTimer = setTimeout(() => this.#filterLocalSuggestions(query), this.debounce);\n return;\n }\n this.#debounceTimer = setTimeout(() => void this.#fetchSuggestions(query), this.debounce);\n }\n\n /** Filters the locally-supplied `suggestions` list for `query`, case-insensitively. */\n #filterLocalSuggestions(query: string) {\n const needle = query.trim().toLowerCase();\n this._suggestions = (this.suggestions ?? [])\n .filter((s) => s.address.toLowerCase().includes(needle))\n .slice(0, 5);\n this._activeIndex = -1;\n this._open = !this.#isDisabled;\n }\n\n /** Fetches suggestions for `query`, cancelling any request still in flight. */\n async #fetchSuggestions(query: string) {\n this.#abortController?.abort();\n const controller = new AbortController();\n this.#abortController = controller;\n try {\n const res = await fetch(this.#buildUrl(query), { signal: controller.signal });\n if (!res.ok) throw new Error(`geocode request failed: ${res.status}`);\n const body = (await res.json()) as { features?: MapboxGeocodeFeature[] };\n if (this.#isDisabled) return;\n this._suggestions = parseFeatures(body.features ?? []);\n this._activeIndex = -1;\n this._open = true;\n } catch {\n // Aborted (superseded by newer keystroke) or a network failure while\n // typing — fail silently and just close the list.\n if (!controller.signal.aborted) {\n this._suggestions = [];\n this._open = false;\n }\n }\n }\n\n #buildUrl(query: string): string {\n const params = new URLSearchParams({\n q: query,\n access_token: this.accessToken,\n autocomplete: \"true\",\n limit: \"5\",\n types: this.types,\n });\n if (this.bbox) params.set(\"bbox\", this.bbox);\n if (this.proximity) params.set(\"proximity\", this.proximity);\n return `${this.endpoint}?${params.toString()}`;\n }\n\n private onKeydown(e: KeyboardEvent) {\n if (this.#isDisabled) return;\n if (e.isComposing || e.keyCode === 229 || this.#isComposing || this.#compositionJustEnded) {\n return;\n }\n if (e.key === \"ArrowDown\") this.#moveActive(1, e);\n else if (e.key === \"ArrowUp\") this.#moveActive(-1, e);\n else if (e.key === \"Enter\") this.#handleEnter(e);\n else if (e.key === \"Escape\") this.#handleEscape(e);\n }\n\n #moveActive(delta: number, e: KeyboardEvent) {\n if (!this._open || this._suggestions.length === 0) return;\n e.preventDefault();\n const n = this._suggestions.length;\n this._activeIndex = (this._activeIndex + delta + n) % n;\n }\n\n #handleEnter(e: KeyboardEvent) {\n const pick = this._suggestions[this._activeIndex] ?? this._suggestions[0];\n if (this._open && pick) {\n e.preventDefault();\n this.#selectSuggestion(pick);\n return;\n }\n if (this.#internals.form) {\n const form = this.#internals.form;\n window.setTimeout(() => {\n if (!e.defaultPrevented && form.isConnected) submitWithDefaultButton(form);\n });\n }\n }\n\n #handleEscape(e: KeyboardEvent) {\n if (!this._open) return;\n e.preventDefault();\n this._open = false;\n }\n\n private onBlur() {\n this._open = false;\n }\n\n private onCompositionStart(): void {\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = null;\n this.#compositionJustEnded = false;\n this.#isComposing = true;\n }\n\n private onCompositionEnd(): void {\n this.#isComposing = false;\n this.#compositionJustEnded = true;\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = setTimeout(() => {\n this.#compositionJustEnded = false;\n this.#compositionEndTimer = null;\n });\n }\n\n /** Clears composition state when the control can no longer receive keys. */\n #resetComposition(): void {\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = null;\n this.#isComposing = false;\n this.#compositionJustEnded = false;\n }\n\n #selectSuggestion(s: AddressSuggestion) {\n this.value = s.address;\n this.#lastPicked = s;\n this._open = false;\n this._suggestions = [];\n this.dispatchEvent(new CustomEvent<AddressSuggestion>(\"address-select\", { detail: s, bubbles: true, composed: true }));\n }\n\n /** Selects on mousedown (not click) so it wins over the input's blur, which closes the list. */\n #onSuggestionMousedown(e: MouseEvent, s: AddressSuggestion) {\n e.preventDefault();\n this.#selectSuggestion(s);\n }\n\n private renderSuggestions() {\n if (!this._open || this.#isDisabled) return nothing;\n return html`\n <ul id=${this.#listboxId} class=\"suggestions\" role=\"listbox\" aria-label=\"Address suggestions\">\n ${this._suggestions.map(\n (s, i) => html`\n <li\n id=${`${this.#listboxId}-option-${i}`}\n role=\"option\"\n aria-selected=${i === this._activeIndex}\n class=\"suggestion ${i === this._activeIndex ? \"active\" : \"\"}\"\n @mousedown=${(e: MouseEvent) => this.#onSuggestionMousedown(e, s)}\n >\n ${s.address}\n </li>\n `,\n )}\n ${this._suggestions.length === 0\n ? html`<li class=\"no-suggestions\" role=\"presentation\">\n <span role=\"status\">No suggestions found</span>\n </li>`\n : nothing}\n </ul>\n `;\n }\n\n override render() {\n const activeDescendant =\n this._open && !this.#isDisabled && this._activeIndex >= 0\n ? `${this.#listboxId}-option-${this._activeIndex}`\n : nothing;\n const expanded = this._open && !this.#isDisabled;\n return html`\n <div>\n <input\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=${expanded}\n aria-controls=${this.#listboxId}\n aria-activedescendant=${activeDescendant}\n .value=${this.value}\n placeholder=${this.placeholder}\n ?required=${this.required}\n ?disabled=${this.#isDisabled}\n autocomplete=\"off\"\n @input=${this.onInput}\n @compositionstart=${this.onCompositionStart}\n @compositionend=${this.onCompositionEnd}\n @keydown=${this.onKeydown}\n @blur=${this.onBlur}\n />\n ${this.renderSuggestions()}\n </div>\n `;\n }\n}\n\n/** Maps Mapbox v6 forward-geocode features to suggestions, skipping ones without a full_address. */\nfunction parseFeatures(features: MapboxGeocodeFeature[]): AddressSuggestion[] {\n const suggestions: AddressSuggestion[] = [];\n for (const f of features) {\n const address = f.properties?.full_address;\n if (!address) continue;\n const [lng, lat] = f.geometry.coordinates;\n suggestions.push({ address, lng, lat });\n }\n return suggestions;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"address-autocomplete\": AddressAutocomplete;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete-input.d.ts","sourceRoot":"","sources":["../src/autocomplete-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAO1E,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBACa,iBAAkB,SAAQ,UAAU;;IAC/C,MAAM,CAAC,cAAc,UAAQ;IAE7B,OAAgB,MAAM,4BAoFpB;IAEF,mFAAmF;IACvE,KAAK,SAAM;IACvB,sDAAsD;IAC1C,WAAW,SAAM;IAC7B,8DAA8D;IACjC,QAAQ,UAAS;IAC9C,0DAA0D;IACd,QAAQ,UAAS;IAC7D,uEAAuE;IAC3D,QAAQ,SAAM;IAC1B,wEAAwE;IAChC,UAAU,SAAO;IACzD,uEAAuE;IAC3C,QAAQ,SAAO;IAC3C,yDAAyD;IACJ,SAAS,SAAK;IACnE;;;;OAIG;IAC6B,OAAO,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAQ;IAEnE,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAS;IAgBvC,mEAAmE;IACnE,IAAI,cAAc,IAAI,kBAAkB,GAAG,IAAI,CAG9C;IAED,UAAmB,UAAU,CAAC,OAAO,EAAE,cAAc,QAQpD;IAED,UAAmB,OAAO,CAAC,OAAO,EAAE,cAAc,QAEjD;IAEQ,oBAAoB,SAK5B;IAED,0FAA0F;IAC1F,iBAAiB,SAKhB;IAED,sEAAsE;IACtE,oBAAoB,CAAC,QAAQ,EAAE,OAAO,QAQrC;IAED,OAAO,CAAC,OAAO;IA8Df,OAAO,CAAC,SAAS;IAuCjB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,iBAAiB;IA0BhB,MAAM,yCA6Bd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,oBAAoB,EAAE,iBAAiB,CAAC;KACzC;CACF"}
1
+ {"version":3,"file":"autocomplete-input.d.ts","sourceRoot":"","sources":["../src/autocomplete-input.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AAO1E,iFAAiF;AACjF,MAAM,WAAW,kBAAkB;IACjC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBACa,iBAAkB,SAAQ,UAAU;;IAC/C,MAAM,CAAC,cAAc,UAAQ;IAE7B,OAAgB,MAAM,4BAsFpB;IAEF,mFAAmF;IACvE,KAAK,SAAM;IACvB,sDAAsD;IAC1C,WAAW,SAAM;IAC7B,8DAA8D;IACjC,QAAQ,UAAS;IAC9C,0DAA0D;IACd,QAAQ,UAAS;IAC7D,uEAAuE;IAC3D,QAAQ,SAAM;IAC1B,wEAAwE;IAChC,UAAU,SAAO;IACzD,uEAAuE;IAC3C,QAAQ,SAAO;IAC3C,yDAAyD;IACJ,SAAS,SAAK;IACnE;;;;OAIG;IAC6B,OAAO,EAAE,kBAAkB,EAAE,GAAG,IAAI,CAAQ;IAEnE,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAS;IAgBvC,mEAAmE;IACnE,IAAI,cAAc,IAAI,kBAAkB,GAAG,IAAI,CAG9C;IAED,UAAmB,UAAU,CAAC,OAAO,EAAE,cAAc,QAQpD;IAED,UAAmB,OAAO,CAAC,OAAO,EAAE,cAAc,QAEjD;IAEQ,oBAAoB,SAK5B;IAED,0FAA0F;IAC1F,iBAAiB,SAKhB;IAED,sEAAsE;IACtE,oBAAoB,CAAC,QAAQ,EAAE,OAAO,QAQrC;IAED,OAAO,CAAC,OAAO;IA8Df,OAAO,CAAC,SAAS;IAuCjB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,gBAAgB;IAgCxB,OAAO,CAAC,iBAAiB;IA0BhB,MAAM,yCA6Bd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,oBAAoB,EAAE,iBAAiB,CAAC;KACzC;CACF"}
@@ -89,12 +89,14 @@ let AutocompleteInput = class AutocompleteInput extends LitElement {
89
89
  "Noto Color Emoji"
90
90
  );
91
91
  font-size: var(--ui-font-size-sm, 0.75rem);
92
+ line-height: var(--ui-line-height-tight, 1.25);
92
93
  color: var(--ui-text, #0f172a);
93
94
  background: var(--ui-surface, #ffffff);
94
- padding: 0.5rem;
95
+ padding: 0.5rem 0.75rem;
95
96
  border: 1px solid var(--ui-border, #e2e8f0);
96
97
  border-radius: var(--ui-radius-sm, 0.25rem);
97
98
  width: 100%;
99
+ height: 2rem;
98
100
  box-sizing: border-box;
99
101
  }
100
102
  input:disabled {
@@ -1 +1 @@
1
- {"version":3,"file":"autocomplete-input.js","sourceRoot":"","sources":["../src/autocomplete-input.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing, type PropertyValues } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\nimport { submitWithDefaultButton } from \"./utils/form.js\";\n\nlet instanceCount = 0;\n\n/** A single autocomplete candidate: an opaque `key` plus its display `value`. */\nexport interface AutocompleteOption {\n key: string;\n value: string;\n}\n\n/**\n * Generic form-associated text input with a suggestion dropdown, for any\n * \"type to filter a list of `{key, value}` options\" use case. Works as a\n * drop-in replacement for a plain `<input>` inside a `<form>`: set `name` on\n * the element itself and consumers keep reading\n * `new FormData(form).get(name)` and calling `form.reset()` unchanged — the\n * submitted value is the picked option's `value`, while `key` is available\n * via the `option-select` event and the `selectedOption` getter for cases\n * that need the underlying id rather than the display text.\n *\n * Supports two suggestion sources:\n * - **API**: set `endpoint` to a URL that, given a `?<query-param>=<text>`\n * query string, responds with a JSON array of `{key, value}` objects.\n * Requests are debounced as the user types.\n * - **Local array**: set `options` to a fixed `AutocompleteOption[]` and the\n * component filters it client-side instead of making any network\n * request. Useful for small/fixed lists, offline use, or tests. Takes\n * priority over `endpoint` whenever it's non-null.\n *\n * @element autocomplete-input\n * @fires option-select - An option was picked; detail: AutocompleteOption.\n */\n@customElement(\"autocomplete-input\")\nexport class AutocompleteInput extends LitElement {\n static formAssociated = true;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n position: relative;\n }\n input {\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size-sm, 0.75rem);\n color: var(--ui-text, #0f172a);\n background: var(--ui-surface, #ffffff);\n padding: 0.5rem;\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n width: 100%;\n box-sizing: border-box;\n }\n input:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n }\n input:focus-visible {\n outline: none;\n border-color: var(--ui-primary, #4f46e5);\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n .suggestions {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: 10;\n max-height: 40vh;\n overflow-y: auto;\n margin: 0.25rem 0 0;\n padding: 0.25rem 0;\n list-style: none;\n background: var(--ui-surface, #ffffff);\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n box-shadow: var(--ui-shadow, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1));\n }\n .suggestion {\n padding: 0.5rem 0.75rem;\n font-size: var(--ui-font-size-sm, 0.75rem);\n cursor: pointer;\n }\n .suggestion.active,\n .suggestion:hover {\n background: var(--ui-surface-muted, #f8fafc);\n }\n .no-suggestions {\n padding: 0.5rem 0.75rem;\n color: var(--ui-text-muted, #64748b);\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-style: italic;\n }\n @media (forced-colors: active) {\n input:focus-visible {\n outline: 2px solid CanvasText;\n outline-offset: 2px;\n box-shadow: none;\n }\n input:disabled {\n color: GrayText;\n opacity: 1;\n }\n .suggestion.active,\n .suggestion:hover {\n color: HighlightText;\n background: Highlight;\n }\n }\n `,\n ];\n\n /** Current input value; also the form-associated value submitted with the form. */\n @property() value = \"\";\n /** Placeholder text shown when the input is empty. */\n @property() placeholder = \"\";\n /** Marks the input as required for native form validation. */\n @property({ type: Boolean }) required = false;\n /** Disables the input and closes its suggestion popup. */\n @property({ type: Boolean, reflect: true }) disabled = false;\n /** API endpoint queried in API mode. Ignored when `options` is set. */\n @property() endpoint = \"\";\n /** Query string parameter name the current input text is sent under. */\n @property({ attribute: \"query-param\" }) queryParam = \"q\";\n /** Debounce delay (ms) before firing a request/filter after typing. */\n @property({ type: Number }) debounce = 300;\n /** Minimum query length before suggestions are shown. */\n @property({ type: Number, attribute: \"min-length\" }) minLength = 3;\n /**\n * Fixed candidate list to filter locally instead of fetching from\n * `endpoint`. When set (non-null), no network request is ever made —\n * this takes priority over the API mode.\n */\n @property({ attribute: false }) options: AutocompleteOption[] | null = null;\n\n @state() private _suggestions: AutocompleteOption[] = [];\n @state() private _open = false;\n @state() private _activeIndex = -1;\n @state() private _formDisabled = false;\n\n #internals = this.attachInternals();\n #lastPicked: AutocompleteOption | null = null;\n #debounceTimer: ReturnType<typeof setTimeout> | null = null;\n #abortController: AbortController | null = null;\n #isComposing = false;\n #compositionJustEnded = false;\n #compositionEndTimer: ReturnType<typeof setTimeout> | null = null;\n readonly #listboxId = `autocomplete-input-listbox-${++instanceCount}`;\n\n /** Whether the host or an ancestor fieldset currently disables the control. */\n get #isDisabled(): boolean {\n return this.disabled || this._formDisabled;\n }\n\n /** Last-picked option, or null once the input diverges from it. */\n get selectedOption(): AutocompleteOption | null {\n if (this.#lastPicked && this.#lastPicked.value === this.value) return this.#lastPicked;\n return null;\n }\n\n protected override willUpdate(changed: PropertyValues) {\n if (changed.has(\"disabled\") && this.#isDisabled) {\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n this._open = false;\n this._activeIndex = -1;\n }\n }\n\n protected override updated(changed: PropertyValues) {\n if (changed.has(\"value\")) this.#internals.setFormValue(this.value);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n }\n\n /** Resets to empty on `form.reset()`, per the form-associated custom element contract. */\n formResetCallback() {\n this.value = \"\";\n this._suggestions = [];\n this._open = false;\n this.#lastPicked = null;\n }\n\n /** Mirrors ancestor fieldset disabled state onto the native input. */\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled;\n if (!disabled) return;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n this._open = false;\n this._activeIndex = -1;\n }\n\n private onInput(e: InputEvent) {\n if (this.#isDisabled) return;\n this.value = (e.target as HTMLInputElement).value;\n this.#lastPicked = null;\n this.#scheduleFetch(this.value);\n }\n\n #scheduleFetch(query: string) {\n if (this.#isDisabled) return;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n if (query.trim().length < this.minLength) {\n this._suggestions = [];\n this._open = false;\n this._activeIndex = -1;\n return;\n }\n if (this.options) {\n // Local mode: filtering is synchronous and cheap, but keep the same\n // debounce as the API mode so the UX doesn't shift between sources.\n this.#debounceTimer = setTimeout(() => this.#filterLocalOptions(query), this.debounce);\n return;\n }\n this.#debounceTimer = setTimeout(() => void this.#fetchOptions(query), this.debounce);\n }\n\n /** Filters the locally-supplied `options` list for `query`, case-insensitively. */\n #filterLocalOptions(query: string) {\n const needle = query.trim().toLowerCase();\n this._suggestions = (this.options ?? [])\n .filter((o) => o.value.toLowerCase().includes(needle))\n .slice(0, 5);\n this._activeIndex = -1;\n this._open = !this.#isDisabled;\n }\n\n /** Fetches options for `query` from `endpoint`, cancelling any request still in flight. */\n async #fetchOptions(query: string) {\n this.#abortController?.abort();\n const controller = new AbortController();\n this.#abortController = controller;\n try {\n const res = await fetch(this.#buildUrl(query), { signal: controller.signal });\n if (!res.ok) throw new Error(`autocomplete request failed: ${res.status}`);\n if (this.#isDisabled) return;\n this._suggestions = ((await res.json()) as AutocompleteOption[]).slice(0, 5);\n this._activeIndex = -1;\n this._open = true;\n } catch {\n // Aborted (superseded by newer keystroke) or a network failure while\n // typing — fail silently and just close the list.\n if (!controller.signal.aborted) {\n this._suggestions = [];\n this._open = false;\n }\n }\n }\n\n #buildUrl(query: string): string {\n const params = new URLSearchParams({ [this.queryParam]: query });\n return `${this.endpoint}?${params.toString()}`;\n }\n\n private onKeydown(e: KeyboardEvent) {\n if (this.#isDisabled) return;\n if (e.isComposing || e.keyCode === 229 || this.#isComposing || this.#compositionJustEnded) {\n return;\n }\n if (e.key === \"ArrowDown\") this.#moveActive(1, e);\n else if (e.key === \"ArrowUp\") this.#moveActive(-1, e);\n else if (e.key === \"Enter\") this.#handleEnter(e);\n else if (e.key === \"Escape\") this.#handleEscape(e);\n }\n\n #moveActive(delta: number, e: KeyboardEvent) {\n if (!this._open || this._suggestions.length === 0) return;\n e.preventDefault();\n const n = this._suggestions.length;\n this._activeIndex = (this._activeIndex + delta + n) % n;\n }\n\n #handleEnter(e: KeyboardEvent) {\n const pick = this._suggestions[this._activeIndex] ?? this._suggestions[0];\n if (this._open && pick) {\n e.preventDefault();\n this.#selectOption(pick);\n return;\n }\n if (this.#internals.form) {\n const form = this.#internals.form;\n window.setTimeout(() => {\n if (!e.defaultPrevented && form.isConnected) submitWithDefaultButton(form);\n });\n }\n }\n\n #handleEscape(e: KeyboardEvent) {\n if (!this._open) return;\n e.preventDefault();\n this._open = false;\n }\n\n private onBlur() {\n this._open = false;\n }\n\n private onCompositionStart(): void {\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = null;\n this.#compositionJustEnded = false;\n this.#isComposing = true;\n }\n\n private onCompositionEnd(): void {\n this.#isComposing = false;\n this.#compositionJustEnded = true;\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = setTimeout(() => {\n this.#compositionJustEnded = false;\n this.#compositionEndTimer = null;\n });\n }\n\n /** Clears composition state when the control can no longer receive keys. */\n #resetComposition(): void {\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = null;\n this.#isComposing = false;\n this.#compositionJustEnded = false;\n }\n\n #selectOption(o: AutocompleteOption) {\n this.value = o.value;\n this.#lastPicked = o;\n this._open = false;\n this._suggestions = [];\n this.dispatchEvent(new CustomEvent<AutocompleteOption>(\"option-select\", { detail: o, bubbles: true, composed: true }));\n }\n\n /** Selects on mousedown (not click) so it wins over the input's blur, which closes the list. */\n #onSuggestionMousedown(e: MouseEvent, o: AutocompleteOption) {\n e.preventDefault();\n this.#selectOption(o);\n }\n\n private renderSuggestions() {\n if (!this._open || this.#isDisabled) return nothing;\n return html`\n <ul id=${this.#listboxId} class=\"suggestions\" role=\"listbox\" aria-label=\"Suggestions\">\n ${this._suggestions.map(\n (o, i) => html`\n <li\n id=${`${this.#listboxId}-option-${i}`}\n role=\"option\"\n aria-selected=${i === this._activeIndex}\n class=\"suggestion ${i === this._activeIndex ? \"active\" : \"\"}\"\n @mousedown=${(e: MouseEvent) => this.#onSuggestionMousedown(e, o)}\n >\n ${o.value}\n </li>\n `,\n )}\n ${this._suggestions.length === 0\n ? html`<li class=\"no-suggestions\" role=\"presentation\">\n <span role=\"status\">No suggestions found</span>\n </li>`\n : nothing}\n </ul>\n `;\n }\n\n override render() {\n const activeDescendant =\n this._open && !this.#isDisabled && this._activeIndex >= 0\n ? `${this.#listboxId}-option-${this._activeIndex}`\n : nothing;\n const expanded = this._open && !this.#isDisabled;\n return html`\n <div>\n <input\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=${expanded}\n aria-controls=${this.#listboxId}\n aria-activedescendant=${activeDescendant}\n .value=${this.value}\n placeholder=${this.placeholder}\n ?required=${this.required}\n ?disabled=${this.#isDisabled}\n autocomplete=\"off\"\n @input=${this.onInput}\n @compositionstart=${this.onCompositionStart}\n @compositionend=${this.onCompositionEnd}\n @keydown=${this.onKeydown}\n @blur=${this.onBlur}\n />\n ${this.renderSuggestions()}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"autocomplete-input\": AutocompleteInput;\n }\n}\n"]}
1
+ {"version":3,"file":"autocomplete-input.js","sourceRoot":"","sources":["../src/autocomplete-input.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing, type PropertyValues } from \"lit\";\nimport { customElement, property, state } from \"lit/decorators.js\";\nimport { tokens } from \"./tokens.js\";\nimport { submitWithDefaultButton } from \"./utils/form.js\";\n\nlet instanceCount = 0;\n\n/** A single autocomplete candidate: an opaque `key` plus its display `value`. */\nexport interface AutocompleteOption {\n key: string;\n value: string;\n}\n\n/**\n * Generic form-associated text input with a suggestion dropdown, for any\n * \"type to filter a list of `{key, value}` options\" use case. Works as a\n * drop-in replacement for a plain `<input>` inside a `<form>`: set `name` on\n * the element itself and consumers keep reading\n * `new FormData(form).get(name)` and calling `form.reset()` unchanged — the\n * submitted value is the picked option's `value`, while `key` is available\n * via the `option-select` event and the `selectedOption` getter for cases\n * that need the underlying id rather than the display text.\n *\n * Supports two suggestion sources:\n * - **API**: set `endpoint` to a URL that, given a `?<query-param>=<text>`\n * query string, responds with a JSON array of `{key, value}` objects.\n * Requests are debounced as the user types.\n * - **Local array**: set `options` to a fixed `AutocompleteOption[]` and the\n * component filters it client-side instead of making any network\n * request. Useful for small/fixed lists, offline use, or tests. Takes\n * priority over `endpoint` whenever it's non-null.\n *\n * @element autocomplete-input\n * @fires option-select - An option was picked; detail: AutocompleteOption.\n */\n@customElement(\"autocomplete-input\")\nexport class AutocompleteInput extends LitElement {\n static formAssociated = true;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n position: relative;\n }\n input {\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size-sm, 0.75rem);\n line-height: var(--ui-line-height-tight, 1.25);\n color: var(--ui-text, #0f172a);\n background: var(--ui-surface, #ffffff);\n padding: 0.5rem 0.75rem;\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n width: 100%;\n height: 2rem;\n box-sizing: border-box;\n }\n input:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n }\n input:focus-visible {\n outline: none;\n border-color: var(--ui-primary, #4f46e5);\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35));\n }\n .suggestions {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n z-index: 10;\n max-height: 40vh;\n overflow-y: auto;\n margin: 0.25rem 0 0;\n padding: 0.25rem 0;\n list-style: none;\n background: var(--ui-surface, #ffffff);\n border: 1px solid var(--ui-border, #e2e8f0);\n border-radius: var(--ui-radius-sm, 0.25rem);\n box-shadow: var(--ui-shadow, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1));\n }\n .suggestion {\n padding: 0.5rem 0.75rem;\n font-size: var(--ui-font-size-sm, 0.75rem);\n cursor: pointer;\n }\n .suggestion.active,\n .suggestion:hover {\n background: var(--ui-surface-muted, #f8fafc);\n }\n .no-suggestions {\n padding: 0.5rem 0.75rem;\n color: var(--ui-text-muted, #64748b);\n font-size: var(--ui-font-size-sm, 0.75rem);\n font-style: italic;\n }\n @media (forced-colors: active) {\n input:focus-visible {\n outline: 2px solid CanvasText;\n outline-offset: 2px;\n box-shadow: none;\n }\n input:disabled {\n color: GrayText;\n opacity: 1;\n }\n .suggestion.active,\n .suggestion:hover {\n color: HighlightText;\n background: Highlight;\n }\n }\n `,\n ];\n\n /** Current input value; also the form-associated value submitted with the form. */\n @property() value = \"\";\n /** Placeholder text shown when the input is empty. */\n @property() placeholder = \"\";\n /** Marks the input as required for native form validation. */\n @property({ type: Boolean }) required = false;\n /** Disables the input and closes its suggestion popup. */\n @property({ type: Boolean, reflect: true }) disabled = false;\n /** API endpoint queried in API mode. Ignored when `options` is set. */\n @property() endpoint = \"\";\n /** Query string parameter name the current input text is sent under. */\n @property({ attribute: \"query-param\" }) queryParam = \"q\";\n /** Debounce delay (ms) before firing a request/filter after typing. */\n @property({ type: Number }) debounce = 300;\n /** Minimum query length before suggestions are shown. */\n @property({ type: Number, attribute: \"min-length\" }) minLength = 3;\n /**\n * Fixed candidate list to filter locally instead of fetching from\n * `endpoint`. When set (non-null), no network request is ever made —\n * this takes priority over the API mode.\n */\n @property({ attribute: false }) options: AutocompleteOption[] | null = null;\n\n @state() private _suggestions: AutocompleteOption[] = [];\n @state() private _open = false;\n @state() private _activeIndex = -1;\n @state() private _formDisabled = false;\n\n #internals = this.attachInternals();\n #lastPicked: AutocompleteOption | null = null;\n #debounceTimer: ReturnType<typeof setTimeout> | null = null;\n #abortController: AbortController | null = null;\n #isComposing = false;\n #compositionJustEnded = false;\n #compositionEndTimer: ReturnType<typeof setTimeout> | null = null;\n readonly #listboxId = `autocomplete-input-listbox-${++instanceCount}`;\n\n /** Whether the host or an ancestor fieldset currently disables the control. */\n get #isDisabled(): boolean {\n return this.disabled || this._formDisabled;\n }\n\n /** Last-picked option, or null once the input diverges from it. */\n get selectedOption(): AutocompleteOption | null {\n if (this.#lastPicked && this.#lastPicked.value === this.value) return this.#lastPicked;\n return null;\n }\n\n protected override willUpdate(changed: PropertyValues) {\n if (changed.has(\"disabled\") && this.#isDisabled) {\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n this._open = false;\n this._activeIndex = -1;\n }\n }\n\n protected override updated(changed: PropertyValues) {\n if (changed.has(\"value\")) this.#internals.setFormValue(this.value);\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n }\n\n /** Resets to empty on `form.reset()`, per the form-associated custom element contract. */\n formResetCallback() {\n this.value = \"\";\n this._suggestions = [];\n this._open = false;\n this.#lastPicked = null;\n }\n\n /** Mirrors ancestor fieldset disabled state onto the native input. */\n formDisabledCallback(disabled: boolean) {\n this._formDisabled = disabled;\n if (!disabled) return;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n this.#resetComposition();\n this.#abortController?.abort();\n this._open = false;\n this._activeIndex = -1;\n }\n\n private onInput(e: InputEvent) {\n if (this.#isDisabled) return;\n this.value = (e.target as HTMLInputElement).value;\n this.#lastPicked = null;\n this.#scheduleFetch(this.value);\n }\n\n #scheduleFetch(query: string) {\n if (this.#isDisabled) return;\n if (this.#debounceTimer) clearTimeout(this.#debounceTimer);\n if (query.trim().length < this.minLength) {\n this._suggestions = [];\n this._open = false;\n this._activeIndex = -1;\n return;\n }\n if (this.options) {\n // Local mode: filtering is synchronous and cheap, but keep the same\n // debounce as the API mode so the UX doesn't shift between sources.\n this.#debounceTimer = setTimeout(() => this.#filterLocalOptions(query), this.debounce);\n return;\n }\n this.#debounceTimer = setTimeout(() => void this.#fetchOptions(query), this.debounce);\n }\n\n /** Filters the locally-supplied `options` list for `query`, case-insensitively. */\n #filterLocalOptions(query: string) {\n const needle = query.trim().toLowerCase();\n this._suggestions = (this.options ?? [])\n .filter((o) => o.value.toLowerCase().includes(needle))\n .slice(0, 5);\n this._activeIndex = -1;\n this._open = !this.#isDisabled;\n }\n\n /** Fetches options for `query` from `endpoint`, cancelling any request still in flight. */\n async #fetchOptions(query: string) {\n this.#abortController?.abort();\n const controller = new AbortController();\n this.#abortController = controller;\n try {\n const res = await fetch(this.#buildUrl(query), { signal: controller.signal });\n if (!res.ok) throw new Error(`autocomplete request failed: ${res.status}`);\n if (this.#isDisabled) return;\n this._suggestions = ((await res.json()) as AutocompleteOption[]).slice(0, 5);\n this._activeIndex = -1;\n this._open = true;\n } catch {\n // Aborted (superseded by newer keystroke) or a network failure while\n // typing — fail silently and just close the list.\n if (!controller.signal.aborted) {\n this._suggestions = [];\n this._open = false;\n }\n }\n }\n\n #buildUrl(query: string): string {\n const params = new URLSearchParams({ [this.queryParam]: query });\n return `${this.endpoint}?${params.toString()}`;\n }\n\n private onKeydown(e: KeyboardEvent) {\n if (this.#isDisabled) return;\n if (e.isComposing || e.keyCode === 229 || this.#isComposing || this.#compositionJustEnded) {\n return;\n }\n if (e.key === \"ArrowDown\") this.#moveActive(1, e);\n else if (e.key === \"ArrowUp\") this.#moveActive(-1, e);\n else if (e.key === \"Enter\") this.#handleEnter(e);\n else if (e.key === \"Escape\") this.#handleEscape(e);\n }\n\n #moveActive(delta: number, e: KeyboardEvent) {\n if (!this._open || this._suggestions.length === 0) return;\n e.preventDefault();\n const n = this._suggestions.length;\n this._activeIndex = (this._activeIndex + delta + n) % n;\n }\n\n #handleEnter(e: KeyboardEvent) {\n const pick = this._suggestions[this._activeIndex] ?? this._suggestions[0];\n if (this._open && pick) {\n e.preventDefault();\n this.#selectOption(pick);\n return;\n }\n if (this.#internals.form) {\n const form = this.#internals.form;\n window.setTimeout(() => {\n if (!e.defaultPrevented && form.isConnected) submitWithDefaultButton(form);\n });\n }\n }\n\n #handleEscape(e: KeyboardEvent) {\n if (!this._open) return;\n e.preventDefault();\n this._open = false;\n }\n\n private onBlur() {\n this._open = false;\n }\n\n private onCompositionStart(): void {\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = null;\n this.#compositionJustEnded = false;\n this.#isComposing = true;\n }\n\n private onCompositionEnd(): void {\n this.#isComposing = false;\n this.#compositionJustEnded = true;\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = setTimeout(() => {\n this.#compositionJustEnded = false;\n this.#compositionEndTimer = null;\n });\n }\n\n /** Clears composition state when the control can no longer receive keys. */\n #resetComposition(): void {\n if (this.#compositionEndTimer) clearTimeout(this.#compositionEndTimer);\n this.#compositionEndTimer = null;\n this.#isComposing = false;\n this.#compositionJustEnded = false;\n }\n\n #selectOption(o: AutocompleteOption) {\n this.value = o.value;\n this.#lastPicked = o;\n this._open = false;\n this._suggestions = [];\n this.dispatchEvent(new CustomEvent<AutocompleteOption>(\"option-select\", { detail: o, bubbles: true, composed: true }));\n }\n\n /** Selects on mousedown (not click) so it wins over the input's blur, which closes the list. */\n #onSuggestionMousedown(e: MouseEvent, o: AutocompleteOption) {\n e.preventDefault();\n this.#selectOption(o);\n }\n\n private renderSuggestions() {\n if (!this._open || this.#isDisabled) return nothing;\n return html`\n <ul id=${this.#listboxId} class=\"suggestions\" role=\"listbox\" aria-label=\"Suggestions\">\n ${this._suggestions.map(\n (o, i) => html`\n <li\n id=${`${this.#listboxId}-option-${i}`}\n role=\"option\"\n aria-selected=${i === this._activeIndex}\n class=\"suggestion ${i === this._activeIndex ? \"active\" : \"\"}\"\n @mousedown=${(e: MouseEvent) => this.#onSuggestionMousedown(e, o)}\n >\n ${o.value}\n </li>\n `,\n )}\n ${this._suggestions.length === 0\n ? html`<li class=\"no-suggestions\" role=\"presentation\">\n <span role=\"status\">No suggestions found</span>\n </li>`\n : nothing}\n </ul>\n `;\n }\n\n override render() {\n const activeDescendant =\n this._open && !this.#isDisabled && this._activeIndex >= 0\n ? `${this.#listboxId}-option-${this._activeIndex}`\n : nothing;\n const expanded = this._open && !this.#isDisabled;\n return html`\n <div>\n <input\n type=\"text\"\n role=\"combobox\"\n aria-autocomplete=\"list\"\n aria-expanded=${expanded}\n aria-controls=${this.#listboxId}\n aria-activedescendant=${activeDescendant}\n .value=${this.value}\n placeholder=${this.placeholder}\n ?required=${this.required}\n ?disabled=${this.#isDisabled}\n autocomplete=\"off\"\n @input=${this.onInput}\n @compositionstart=${this.onCompositionStart}\n @compositionend=${this.onCompositionEnd}\n @keydown=${this.onKeydown}\n @blur=${this.onBlur}\n />\n ${this.renderSuggestions()}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"autocomplete-input\": AutocompleteInput;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"calendar-month.d.ts","sourceRoot":"","sources":["../src/calendar-month.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAoBrD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,kCAAkC;IACS,IAAI,EAAE,MAAM,CAA4B;IAEnF,0CAA0C;IACC,KAAK,SAAK;IAGrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmB;IAElD,2FAA2F;IAClF,OAAO,CAAC,eAAe,CAAK;IAErC,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAE5C,OAAgB,MAAM,4BA6MpB;IAEF,+EAA+E;IACtE,iBAAiB,IAAI,IAAI,CAWjC;IAED,+DAA+D;IACtD,oBAAoB,IAAI,IAAI,CAGpC;IAED,wFAAwF;IACxF,UAAmB,OAAO,IAAI,IAAI,CAEjC;IAED,kFAAkF;IAClF,OAAO,CAAC,iBAAiB;IAIzB,sEAAsE;IACtE,OAAO,CAAC,SAAS;IAIjB,8EAA8E;IAC9E,OAAO,CAAC,aAAa;IASrB,oEAAoE;IACpE,OAAO,CAAC,SAAS;IAIjB,kFAAkF;IAClF,OAAO,CAAC,oBAAoB;IAQ5B,uFAAuF;IACvF,OAAO,CAAC,sBAAsB;IAa9B,8EAA8E;IAC9E,OAAO,CAAC,gBAAgB;IAgBxB,iGAAiG;IACjG,OAAO,CAAC,cAAc;IAMtB,oFAAoF;IACpF,OAAO,CAAC,gBAAgB;IAiCxB,kFAAkF;IAClF,OAAO,CAAC,oBAAoB;IAsB5B,wGAAwG;IACxG,OAAO,CAAC,eAAe;IA8CvB,UAAmB,MAAM,yCAyCxB;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,aAAa,CAAC;KACjC;CACF"}
1
+ {"version":3,"file":"calendar-month.d.ts","sourceRoot":"","sources":["../src/calendar-month.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAoBrD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,kCAAkC;IACS,IAAI,EAAE,MAAM,CAA4B;IAEnF,0CAA0C;IACC,KAAK,SAAK;IAGrD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAmB;IAElD,2FAA2F;IAClF,OAAO,CAAC,eAAe,CAAK;IAErC,OAAO,CAAC,gBAAgB,CAAC,CAAmB;IAE5C,OAAgB,MAAM,4BA8MpB;IAEF,+EAA+E;IACtE,iBAAiB,IAAI,IAAI,CAWjC;IAED,+DAA+D;IACtD,oBAAoB,IAAI,IAAI,CAGpC;IAED,wFAAwF;IACxF,UAAmB,OAAO,IAAI,IAAI,CAEjC;IAED,kFAAkF;IAClF,OAAO,CAAC,iBAAiB;IAIzB,sEAAsE;IACtE,OAAO,CAAC,SAAS;IAIjB,8EAA8E;IAC9E,OAAO,CAAC,aAAa;IASrB,oEAAoE;IACpE,OAAO,CAAC,SAAS;IAIjB,kFAAkF;IAClF,OAAO,CAAC,oBAAoB;IAQ5B,uFAAuF;IACvF,OAAO,CAAC,sBAAsB;IAa9B,8EAA8E;IAC9E,OAAO,CAAC,gBAAgB;IAgBxB,iGAAiG;IACjG,OAAO,CAAC,cAAc;IAMtB,oFAAoF;IACpF,OAAO,CAAC,gBAAgB;IAiCxB,kFAAkF;IAClF,OAAO,CAAC,oBAAoB;IAsB5B,wGAAwG;IACxG,OAAO,CAAC,eAAe;IA8CvB,UAAmB,MAAM,yCAyCxB;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,gBAAgB,EAAE,aAAa,CAAC;KACjC;CACF"}
@@ -59,8 +59,9 @@ let CalendarMonth = class CalendarMonth extends LitElement {
59
59
  .month-name {
60
60
  margin: 0 0 0.5rem;
61
61
  color: var(--ui-text, #0f172a);
62
- font-size: var(--ui-font-size, 0.875rem);
63
- font-weight: 600;
62
+ font-size: var(--ui-font-size-lg, 1rem);
63
+ font-weight: var(--ui-font-weight-semibold, 600);
64
+ line-height: var(--ui-line-height-tight, 1.25);
64
65
  }
65
66
  table {
66
67
  width: 100%;
@@ -86,7 +87,7 @@ let CalendarMonth = class CalendarMonth extends LitElement {
86
87
  }
87
88
  .day-row.today .day-number {
88
89
  color: var(--ui-primary, #4f46e5);
89
- font-weight: 700;
90
+ font-weight: var(--ui-font-weight-bold, 700);
90
91
  }
91
92
  .day-weekday {
92
93
  width: 2.25rem;
@@ -95,10 +96,10 @@ let CalendarMonth = class CalendarMonth extends LitElement {
95
96
  }
96
97
  .day-row.today .day-weekday {
97
98
  color: var(--ui-primary, #4f46e5);
98
- font-weight: 600;
99
+ font-weight: var(--ui-font-weight-semibold, 600);
99
100
  }
100
101
  .day-row.weekend .day-weekday {
101
- font-weight: 600;
102
+ font-weight: var(--ui-font-weight-semibold, 600);
102
103
  }
103
104
  .lane-cell {
104
105
  padding: 0.25rem 0.5rem;
@@ -161,7 +162,7 @@ let CalendarMonth = class CalendarMonth extends LitElement {
161
162
  }
162
163
  .entry-title {
163
164
  box-sizing: border-box;
164
- font-weight: 500;
165
+ font-weight: var(--ui-font-weight-medium, 500);
165
166
  padding: 0.25rem 0.5rem;
166
167
  pointer-events: none;
167
168
  white-space: nowrap;
@@ -176,7 +177,7 @@ let CalendarMonth = class CalendarMonth extends LitElement {
176
177
  -webkit-box-orient: vertical;
177
178
  -webkit-line-clamp: var(--entry-detail-lines, 1);
178
179
  font-size: var(--ui-font-size-xs, 0.6875rem);
179
- font-weight: 400;
180
+ font-weight: var(--ui-font-weight-regular, 400);
180
181
  line-height: 1.15;
181
182
  overflow-wrap: anywhere;
182
183
  text-overflow: ellipsis;
@@ -209,7 +210,7 @@ let CalendarMonth = class CalendarMonth extends LitElement {
209
210
  border-top: 1px solid color-mix(in srgb, currentColor 20%, transparent);
210
211
  padding-top: 0.25rem;
211
212
  font-size: var(--ui-font-size-xs, 0.6875rem);
212
- font-weight: 500;
213
+ font-weight: var(--ui-font-weight-medium, 500);
213
214
  line-height: 1.15;
214
215
  overflow: hidden;
215
216
  text-overflow: ellipsis;
@@ -1 +1 @@
1
- {"version":3,"file":"calendar-month.js","sourceRoot":"","sources":["../src/calendar-month.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, property, queryAssignedElements, state } from \"lit/decorators.js\";\nimport { repeat } from \"lit/directives/repeat.js\";\nimport { CalendarEntry } from \"./calendar-entry.js\";\nimport { tokens } from \"./tokens.js\";\nimport {\n CALENDAR_ENTRY_ATTRIBUTES,\n WEEKDAY_ABBR,\n assignLanes,\n daysInMonth,\n isWeekend,\n monthName,\n overlapsRange,\n readCalendarEntryElement,\n resolveEntry,\n toIsoDate,\n type LanedEntry,\n type ResolvedCalendarEntry,\n} from \"./utils/calendar.js\";\n\n/**\n * One month rendered as a top-to-bottom list of days — weekends and today\n * highlighted, with declarative `calendar-entry` children shown as colored\n * bars spanning the days they cover. An entry's title uses its first visible\n * day; every remaining visible day becomes one shared body for wrapped\n * details and an optional ending footer. Overlapping entries stack into\n * side-by-side lanes rather than being layered/hidden. Read-only.\n *\n * Lanes are computed independently per instance, from only the entries\n * overlapping this month — an entry spanning a month boundary may therefore\n * land in a different lane index in the adjacent month's `calendar-month`.\n * This is an accepted v1 limitation: cross-month lane continuity would\n * require a shared parent (`calendar-year`) to assign lanes globally.\n *\n * Entry attributes and slotted title/detail text are observed, so a\n * standalone month re-renders when consumers update declarative metadata.\n *\n * @element calendar-month\n * @slot - Declarative `calendar-entry` elements to render for this month.\n */\n@customElement(\"calendar-month\")\nexport class CalendarMonth extends LitElement {\n /** Calendar year, e.g. `2026`. */\n @property({ type: Number, reflect: true }) year: number = new Date().getFullYear();\n\n /** Calendar month, 1-12 (January = 1). */\n @property({ type: Number, reflect: true }) month = 1;\n\n @queryAssignedElements({ selector: \"calendar-entry\" })\n private readonly _entryElements!: CalendarEntry[];\n\n /** Bumped when entry elements, attributes, or slotted text change to force a re-render. */\n @state() private _entriesVersion = 0;\n\n private _entriesObserver?: MutationObserver;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size-sm, 0.75rem);\n }\n .month-name {\n margin: 0 0 0.5rem;\n color: var(--ui-text, #0f172a);\n font-size: var(--ui-font-size, 0.875rem);\n font-weight: 600;\n }\n table {\n width: 100%;\n border-collapse: collapse;\n table-layout: fixed;\n }\n .day-row td {\n padding: 0.25rem 0.5rem;\n border-bottom: 1px solid var(--ui-border, #e2e8f0);\n }\n .day-row.weekend {\n background: var(--ui-surface-muted, #f8fafc);\n }\n .day-row.today {\n background: color-mix(in srgb, var(--ui-primary, #4f46e5) 10%, transparent);\n }\n .day-number {\n width: 1.5rem;\n color: var(--ui-text-muted, #64748b);\n font-variant-numeric: tabular-nums;\n text-align: right;\n white-space: nowrap;\n }\n .day-row.today .day-number {\n color: var(--ui-primary, #4f46e5);\n font-weight: 700;\n }\n .day-weekday {\n width: 2.25rem;\n color: var(--ui-text-muted, #64748b);\n white-space: nowrap;\n }\n .day-row.today .day-weekday {\n color: var(--ui-primary, #4f46e5);\n font-weight: 600;\n }\n .day-row.weekend .day-weekday {\n font-weight: 600;\n }\n .lane-cell {\n padding: 0.25rem 0.5rem;\n }\n .entry-bar {\n border-radius: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n transition: box-shadow 120ms ease;\n white-space: nowrap;\n }\n .entry-bar.entry-hovered,\n .entry-bar.entry-focused {\n box-shadow: inset 0 0 0 100vmax var(--ui-hover-overlay, rgb(255 255 255 / 0.32));\n }\n .entry-bar.segment-single {\n border-radius: var(--ui-radius-sm, 0.25rem);\n }\n .entry-bar.segment-start {\n border-radius: var(--ui-radius-sm, 0.25rem) var(--ui-radius-sm, 0.25rem) 0 0;\n }\n .entry-bar.segment-end {\n border-radius: 0 0 var(--ui-radius-sm, 0.25rem) var(--ui-radius-sm, 0.25rem);\n }\n .entry-bar.segment-start,\n .entry-bar.segment-middle {\n border-bottom: 0;\n }\n .entry-bar.neutral {\n background: color-mix(in srgb, var(--ui-text-muted, #64748b) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-text-muted, #64748b);\n }\n .entry-bar.info {\n background: color-mix(in srgb, var(--ui-info, #0ea5e9) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-info, #0ea5e9);\n }\n .entry-bar.primary {\n background: color-mix(in srgb, var(--ui-primary, #4f46e5) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-primary, #4f46e5);\n }\n .entry-bar.success {\n background: color-mix(in srgb, var(--ui-success, #16a34a) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-success, #16a34a);\n }\n .entry-bar.warning {\n background: color-mix(in srgb, var(--ui-warning, #d97706) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-warning, #d97706);\n }\n .entry-bar.danger {\n background: color-mix(in srgb, var(--ui-danger, #dc2626) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-danger, #dc2626);\n }\n .entry-line {\n display: block;\n overflow: hidden;\n }\n .day-row td.entry-title-cell {\n position: relative;\n padding: 0;\n }\n .entry-title {\n box-sizing: border-box;\n font-weight: 500;\n padding: 0.25rem 0.5rem;\n pointer-events: none;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n .entry-details {\n display: -webkit-box;\n min-height: 0;\n max-height: var(--entry-detail-max-height, 1.15em);\n flex: 0 0 auto;\n overflow: hidden;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: var(--entry-detail-lines, 1);\n font-size: var(--ui-font-size-xs, 0.6875rem);\n font-weight: 400;\n line-height: 1.15;\n overflow-wrap: anywhere;\n text-overflow: ellipsis;\n white-space: normal;\n }\n .entry-detail {\n min-height: 1.15em;\n }\n .day-row td.entry-body-cell {\n position: relative;\n padding: 0;\n vertical-align: top;\n }\n .entry-body {\n position: absolute;\n inset: 0;\n box-sizing: border-box;\n display: flex;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n padding: 0.25rem 0.5rem;\n color: inherit;\n pointer-events: none;\n }\n .entry-footer {\n flex: 0 0 auto;\n min-height: 1.15em;\n margin-top: auto;\n border-top: 1px solid color-mix(in srgb, currentColor 20%, transparent);\n padding-top: 0.25rem;\n font-size: var(--ui-font-size-xs, 0.6875rem);\n font-weight: 500;\n line-height: 1.15;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .entry-link {\n position: absolute;\n z-index: 1;\n inset: 0;\n border-radius: inherit;\n color: inherit;\n cursor: pointer;\n text-decoration: none;\n }\n .entry-link:focus-visible {\n outline: 2px solid var(--ui-primary, #4f46e5);\n outline-offset: -2px;\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35)) inset;\n }\n @media (forced-colors: active) {\n .entry-link:focus-visible {\n outline-color: Highlight;\n box-shadow: none;\n }\n }\n @media (prefers-reduced-motion: reduce) {\n .entry-bar {\n transition: none;\n }\n }\n slot {\n display: none;\n }\n `,\n ];\n\n /** Observes declarative entry attributes and slotted text for live updates. */\n override connectedCallback(): void {\n super.connectedCallback();\n this._entriesVersion++;\n this._entriesObserver ??= new MutationObserver(() => this._entriesVersion++);\n this._entriesObserver.observe(this, {\n attributes: true,\n attributeFilter: CALENDAR_ENTRY_ATTRIBUTES,\n characterData: true,\n childList: true,\n subtree: true,\n });\n }\n\n /** Releases the entry observer when this month disconnects. */\n override disconnectedCallback(): void {\n this._entriesObserver?.disconnect();\n super.disconnectedCallback();\n }\n\n /** Restores hover/focus classes from the live DOM after Lit updates or reuses cells. */\n protected override updated(): void {\n this._syncEntryInteractions();\n }\n\n /** Re-renders when declarative `calendar-entry` children are added or removed. */\n private _handleSlotChange(): void {\n this._entriesVersion++;\n }\n\n /** Finds the laned entry (if any) covering `date` in a given lane. */\n private _entryFor(laned: LanedEntry[], lane: number, date: Date): LanedEntry | undefined {\n return laned.find((entry) => entry.lane === lane && entry.startDate <= date && date <= entry.endDate);\n }\n\n /** Classifies one day of an entry so only the outer endpoints are rounded. */\n private _segmentClass(entry: LanedEntry, date: Date): string {\n const startsHere = date.getTime() === entry.startDate.getTime();\n const endsHere = date.getTime() === entry.endDate.getTime();\n if (startsHere && endsHere) return \"segment-single\";\n if (startsHere) return \"segment-start\";\n if (endsHere) return \"segment-end\";\n return \"segment-middle\";\n }\n\n /** Current render key shared by an entry's title and body cells. */\n private _entryKey(entry: LanedEntry): string {\n return `${entry.lane}|${entry.start}|${entry.end}|${entry.label}|${entry.href ?? \"\"}`;\n }\n\n /** Toggles one interaction class on every rendered cell belonging to an entry. */\n private _setEntryInteraction(entryKey: string, className: string, active: boolean): void {\n for (const cell of this.renderRoot.querySelectorAll<HTMLElement>(\".entry-bar\")) {\n if (cell.dataset.entryKey === entryKey) {\n cell.classList.toggle(className, active);\n }\n }\n }\n\n /** Reconciles classes against the links actually hovered or focused after a render. */\n private _syncEntryInteractions(): void {\n for (const cell of this.renderRoot.querySelectorAll<HTMLElement>(\".entry-bar\")) {\n cell.classList.remove(\"entry-hovered\", \"entry-focused\");\n }\n for (const link of this.renderRoot.querySelectorAll<HTMLElement>(\".entry-link:hover\")) {\n this._setEntryInteraction(link.dataset.entryKey ?? \"\", \"entry-hovered\", true);\n }\n const activeElement = this.shadowRoot?.activeElement;\n if (activeElement instanceof HTMLElement && activeElement.matches(\".entry-link\")) {\n this._setEntryInteraction(activeElement.dataset.entryKey ?? \"\", \"entry-focused\", true);\n }\n }\n\n /** Renders a transparent full-cell link without wrapping the visible text. */\n private _renderEntryLink(entry: LanedEntry, accessibleText: string) {\n const entryKey = this._entryKey(entry);\n return entry.href\n ? html`<a\n class=\"entry-link\"\n href=${entry.href}\n aria-label=${accessibleText}\n data-entry-key=${entryKey}\n @pointerenter=${() => this._setEntryInteraction(entryKey, \"entry-hovered\", true)}\n @pointerleave=${() => this._setEntryInteraction(entryKey, \"entry-hovered\", false)}\n @focus=${() => this._setEntryInteraction(entryKey, \"entry-focused\", true)}\n @blur=${() => this._setEntryInteraction(entryKey, \"entry-focused\", false)}\n ></a>`\n : nothing;\n }\n\n /** Joins the event title, details, and visible footer for tooltips and accessible link names. */\n private _entryBodyText(entry: LanedEntry, showFooter: boolean): string {\n return [entry.label, ...(entry.details ?? []), showFooter ? entry.footer : undefined]\n .filter((line): line is string => Boolean(line))\n .join(\"\\n\");\n }\n\n /** Renders the shared details body, with the footer reserved at its bottom edge. */\n private _renderEntryBody(\n entry: LanedEntry,\n showFooter: boolean,\n detailLineClamp: number,\n showTitleFallback = false,\n ) {\n const sourceDetails = entry.details ?? [];\n const footer = showFooter ? entry.footer : undefined;\n const details =\n showTitleFallback && sourceDetails.length === 0 && !footer\n ? [entry.label]\n : sourceDetails;\n const bodyText = this._entryBodyText(entry, showFooter);\n return html`\n ${this._renderEntryLink(entry, bodyText)}\n <div class=\"entry-body\" aria-hidden=${entry.href ? \"true\" : nothing}>\n ${detailLineClamp > 0 && details.length > 0\n ? html`\n <div\n class=\"entry-details\"\n style=${`--entry-detail-lines: ${detailLineClamp}; --entry-detail-max-height: ${\n detailLineClamp * 1.15\n }em`}\n >\n ${details.map((detail) => html`<div class=\"entry-detail\">${detail}</div>`)}\n </div>\n `\n : nothing}\n ${footer ? html`<div class=\"entry-footer\" title=${footer}>${footer}</div>` : nothing}\n </div>\n `;\n }\n\n /** Renders a row-spanning body cell with whole-line detail and footer budgets. */\n private _renderEntryBodyCell(\n entry: LanedEntry,\n bodyRows: number,\n reachesEventEnd: boolean,\n showTitleFallback = false,\n ) {\n const segmentClass = reachesEventEnd ? \"segment-end\" : \"segment-middle\";\n const footerLineBudget = reachesEventEnd && entry.footer ? 1 : 0;\n const detailLineClamp = Math.max(0, bodyRows - footerLineBudget);\n const bodyText = this._entryBodyText(entry, reachesEventEnd);\n return html`\n <td\n class=\"lane-cell entry-bar entry-body-cell ${entry.color} ${segmentClass}\"\n data-entry-key=${this._entryKey(entry)}\n rowspan=${bodyRows}\n title=${entry.href ? nothing : bodyText}\n >\n ${this._renderEntryBody(entry, reachesEventEnd, detailLineClamp, showTitleFallback)}\n </td>\n `;\n }\n\n /** Renders a lane's title/body cell, skips rows covered by a body rowspan, or emits an empty spacer. */\n private _renderLaneCell(\n laned: LanedEntry[],\n lane: number,\n date: Date,\n monthStart: Date,\n monthEnd: Date,\n ) {\n const entry = this._entryFor(laned, lane, date);\n if (!entry) {\n return html`<td class=\"lane-cell empty\"></td>`;\n }\n\n const firstVisibleDay = entry.startDate > monthStart ? entry.startDate : monthStart;\n const lastVisibleDay = entry.endDate < monthEnd ? entry.endDate : monthEnd;\n const dayOffset = date.getDate() - firstVisibleDay.getDate();\n const visibleDayCount = lastVisibleDay.getDate() - firstVisibleDay.getDate() + 1;\n const isMultiDayEntry = entry.startDate.getTime() !== entry.endDate.getTime();\n const isEndingOnlyClip =\n visibleDayCount === 1 &&\n isMultiDayEntry &&\n date.getTime() === entry.endDate.getTime();\n if (isEndingOnlyClip) {\n return this._renderEntryBodyCell(entry, 1, true, true);\n }\n if (dayOffset > 1) return nothing;\n\n if (dayOffset === 1) {\n const bodyRows = visibleDayCount - 1;\n const reachesEventEnd = lastVisibleDay.getTime() === entry.endDate.getTime();\n return this._renderEntryBodyCell(entry, bodyRows, reachesEventEnd);\n }\n\n return html`\n <td\n class=\"lane-cell entry-bar entry-title-cell ${entry.color} ${this._segmentClass(entry, date)}\"\n data-entry-key=${this._entryKey(entry)}\n title=${entry.href ? nothing : entry.label}\n >\n ${this._renderEntryLink(entry, entry.label)}\n <span class=\"entry-line entry-title\" aria-hidden=${entry.href ? \"true\" : nothing}>\n ${entry.label}\n </span>\n </td>\n `;\n }\n\n protected override render() {\n const totalDays = daysInMonth(this.year, this.month);\n const monthStart = new Date(this.year, this.month - 1, 1);\n const monthEnd = new Date(this.year, this.month - 1, totalDays);\n\n const resolved = this._entryElements\n .map(readCalendarEntryElement)\n .map(resolveEntry)\n .filter((entry): entry is ResolvedCalendarEntry => entry !== null)\n .filter((entry) => overlapsRange(entry, monthStart, monthEnd));\n const { entries: laned, laneCount } = assignLanes(resolved);\n const todayIso = toIsoDate(new Date());\n const lanes = Array.from({ length: Math.max(laneCount, 1) }, (_, i) => i);\n\n return html`\n <div class=\"month\">\n <h4 class=\"month-name\">${monthName(this.month)} ${this.year}</h4>\n <table>\n <tbody>\n ${repeat(\n Array.from({ length: totalDays }, (_, i) => i + 1),\n (d) => d,\n (d) => {\n const date = new Date(this.year, this.month - 1, d);\n const dow = date.getDay();\n const weekendCls = isWeekend(date) ? \"weekend\" : \"\";\n const todayCls = toIsoDate(date) === todayIso ? \"today\" : \"\";\n return html`\n <tr class=\"day-row ${weekendCls} ${todayCls}\">\n <td class=\"day-number\">${d}</td>\n <td class=\"day-weekday\">${WEEKDAY_ABBR[dow]}</td>\n ${lanes.map((lane) => this._renderLaneCell(laned, lane, date, monthStart, monthEnd))}\n </tr>\n `;\n },\n )}\n </tbody>\n </table>\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"calendar-month\": CalendarMonth;\n }\n}\n"]}
1
+ {"version":3,"file":"calendar-month.js","sourceRoot":"","sources":["../src/calendar-month.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, css, html, nothing } from \"lit\";\nimport { customElement, property, queryAssignedElements, state } from \"lit/decorators.js\";\nimport { repeat } from \"lit/directives/repeat.js\";\nimport { CalendarEntry } from \"./calendar-entry.js\";\nimport { tokens } from \"./tokens.js\";\nimport {\n CALENDAR_ENTRY_ATTRIBUTES,\n WEEKDAY_ABBR,\n assignLanes,\n daysInMonth,\n isWeekend,\n monthName,\n overlapsRange,\n readCalendarEntryElement,\n resolveEntry,\n toIsoDate,\n type LanedEntry,\n type ResolvedCalendarEntry,\n} from \"./utils/calendar.js\";\n\n/**\n * One month rendered as a top-to-bottom list of days — weekends and today\n * highlighted, with declarative `calendar-entry` children shown as colored\n * bars spanning the days they cover. An entry's title uses its first visible\n * day; every remaining visible day becomes one shared body for wrapped\n * details and an optional ending footer. Overlapping entries stack into\n * side-by-side lanes rather than being layered/hidden. Read-only.\n *\n * Lanes are computed independently per instance, from only the entries\n * overlapping this month — an entry spanning a month boundary may therefore\n * land in a different lane index in the adjacent month's `calendar-month`.\n * This is an accepted v1 limitation: cross-month lane continuity would\n * require a shared parent (`calendar-year`) to assign lanes globally.\n *\n * Entry attributes and slotted title/detail text are observed, so a\n * standalone month re-renders when consumers update declarative metadata.\n *\n * @element calendar-month\n * @slot - Declarative `calendar-entry` elements to render for this month.\n */\n@customElement(\"calendar-month\")\nexport class CalendarMonth extends LitElement {\n /** Calendar year, e.g. `2026`. */\n @property({ type: Number, reflect: true }) year: number = new Date().getFullYear();\n\n /** Calendar month, 1-12 (January = 1). */\n @property({ type: Number, reflect: true }) month = 1;\n\n @queryAssignedElements({ selector: \"calendar-entry\" })\n private readonly _entryElements!: CalendarEntry[];\n\n /** Bumped when entry elements, attributes, or slotted text change to force a re-render. */\n @state() private _entriesVersion = 0;\n\n private _entriesObserver?: MutationObserver;\n\n static override styles = [\n tokens,\n css`\n :host {\n display: block;\n font-family: var(\n --ui-font,\n ui-sans-serif,\n system-ui,\n sans-serif,\n \"Apple Color Emoji\",\n \"Segoe UI Emoji\",\n \"Segoe UI Symbol\",\n \"Noto Color Emoji\"\n );\n font-size: var(--ui-font-size-sm, 0.75rem);\n }\n .month-name {\n margin: 0 0 0.5rem;\n color: var(--ui-text, #0f172a);\n font-size: var(--ui-font-size-lg, 1rem);\n font-weight: var(--ui-font-weight-semibold, 600);\n line-height: var(--ui-line-height-tight, 1.25);\n }\n table {\n width: 100%;\n border-collapse: collapse;\n table-layout: fixed;\n }\n .day-row td {\n padding: 0.25rem 0.5rem;\n border-bottom: 1px solid var(--ui-border, #e2e8f0);\n }\n .day-row.weekend {\n background: var(--ui-surface-muted, #f8fafc);\n }\n .day-row.today {\n background: color-mix(in srgb, var(--ui-primary, #4f46e5) 10%, transparent);\n }\n .day-number {\n width: 1.5rem;\n color: var(--ui-text-muted, #64748b);\n font-variant-numeric: tabular-nums;\n text-align: right;\n white-space: nowrap;\n }\n .day-row.today .day-number {\n color: var(--ui-primary, #4f46e5);\n font-weight: var(--ui-font-weight-bold, 700);\n }\n .day-weekday {\n width: 2.25rem;\n color: var(--ui-text-muted, #64748b);\n white-space: nowrap;\n }\n .day-row.today .day-weekday {\n color: var(--ui-primary, #4f46e5);\n font-weight: var(--ui-font-weight-semibold, 600);\n }\n .day-row.weekend .day-weekday {\n font-weight: var(--ui-font-weight-semibold, 600);\n }\n .lane-cell {\n padding: 0.25rem 0.5rem;\n }\n .entry-bar {\n border-radius: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n transition: box-shadow 120ms ease;\n white-space: nowrap;\n }\n .entry-bar.entry-hovered,\n .entry-bar.entry-focused {\n box-shadow: inset 0 0 0 100vmax var(--ui-hover-overlay, rgb(255 255 255 / 0.32));\n }\n .entry-bar.segment-single {\n border-radius: var(--ui-radius-sm, 0.25rem);\n }\n .entry-bar.segment-start {\n border-radius: var(--ui-radius-sm, 0.25rem) var(--ui-radius-sm, 0.25rem) 0 0;\n }\n .entry-bar.segment-end {\n border-radius: 0 0 var(--ui-radius-sm, 0.25rem) var(--ui-radius-sm, 0.25rem);\n }\n .entry-bar.segment-start,\n .entry-bar.segment-middle {\n border-bottom: 0;\n }\n .entry-bar.neutral {\n background: color-mix(in srgb, var(--ui-text-muted, #64748b) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-text-muted, #64748b);\n }\n .entry-bar.info {\n background: color-mix(in srgb, var(--ui-info, #0ea5e9) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-info, #0ea5e9);\n }\n .entry-bar.primary {\n background: color-mix(in srgb, var(--ui-primary, #4f46e5) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-primary, #4f46e5);\n }\n .entry-bar.success {\n background: color-mix(in srgb, var(--ui-success, #16a34a) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-success, #16a34a);\n }\n .entry-bar.warning {\n background: color-mix(in srgb, var(--ui-warning, #d97706) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-warning, #d97706);\n }\n .entry-bar.danger {\n background: color-mix(in srgb, var(--ui-danger, #dc2626) 15%, var(--ui-surface, #ffffff));\n color: var(--ui-danger, #dc2626);\n }\n .entry-line {\n display: block;\n overflow: hidden;\n }\n .day-row td.entry-title-cell {\n position: relative;\n padding: 0;\n }\n .entry-title {\n box-sizing: border-box;\n font-weight: var(--ui-font-weight-medium, 500);\n padding: 0.25rem 0.5rem;\n pointer-events: none;\n white-space: nowrap;\n text-overflow: ellipsis;\n }\n .entry-details {\n display: -webkit-box;\n min-height: 0;\n max-height: var(--entry-detail-max-height, 1.15em);\n flex: 0 0 auto;\n overflow: hidden;\n -webkit-box-orient: vertical;\n -webkit-line-clamp: var(--entry-detail-lines, 1);\n font-size: var(--ui-font-size-xs, 0.6875rem);\n font-weight: var(--ui-font-weight-regular, 400);\n line-height: 1.15;\n overflow-wrap: anywhere;\n text-overflow: ellipsis;\n white-space: normal;\n }\n .entry-detail {\n min-height: 1.15em;\n }\n .day-row td.entry-body-cell {\n position: relative;\n padding: 0;\n vertical-align: top;\n }\n .entry-body {\n position: absolute;\n inset: 0;\n box-sizing: border-box;\n display: flex;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n padding: 0.25rem 0.5rem;\n color: inherit;\n pointer-events: none;\n }\n .entry-footer {\n flex: 0 0 auto;\n min-height: 1.15em;\n margin-top: auto;\n border-top: 1px solid color-mix(in srgb, currentColor 20%, transparent);\n padding-top: 0.25rem;\n font-size: var(--ui-font-size-xs, 0.6875rem);\n font-weight: var(--ui-font-weight-medium, 500);\n line-height: 1.15;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .entry-link {\n position: absolute;\n z-index: 1;\n inset: 0;\n border-radius: inherit;\n color: inherit;\n cursor: pointer;\n text-decoration: none;\n }\n .entry-link:focus-visible {\n outline: 2px solid var(--ui-primary, #4f46e5);\n outline-offset: -2px;\n box-shadow: var(--ui-focus-ring, 0 0 0 3px rgb(79 70 229 / 0.35)) inset;\n }\n @media (forced-colors: active) {\n .entry-link:focus-visible {\n outline-color: Highlight;\n box-shadow: none;\n }\n }\n @media (prefers-reduced-motion: reduce) {\n .entry-bar {\n transition: none;\n }\n }\n slot {\n display: none;\n }\n `,\n ];\n\n /** Observes declarative entry attributes and slotted text for live updates. */\n override connectedCallback(): void {\n super.connectedCallback();\n this._entriesVersion++;\n this._entriesObserver ??= new MutationObserver(() => this._entriesVersion++);\n this._entriesObserver.observe(this, {\n attributes: true,\n attributeFilter: CALENDAR_ENTRY_ATTRIBUTES,\n characterData: true,\n childList: true,\n subtree: true,\n });\n }\n\n /** Releases the entry observer when this month disconnects. */\n override disconnectedCallback(): void {\n this._entriesObserver?.disconnect();\n super.disconnectedCallback();\n }\n\n /** Restores hover/focus classes from the live DOM after Lit updates or reuses cells. */\n protected override updated(): void {\n this._syncEntryInteractions();\n }\n\n /** Re-renders when declarative `calendar-entry` children are added or removed. */\n private _handleSlotChange(): void {\n this._entriesVersion++;\n }\n\n /** Finds the laned entry (if any) covering `date` in a given lane. */\n private _entryFor(laned: LanedEntry[], lane: number, date: Date): LanedEntry | undefined {\n return laned.find((entry) => entry.lane === lane && entry.startDate <= date && date <= entry.endDate);\n }\n\n /** Classifies one day of an entry so only the outer endpoints are rounded. */\n private _segmentClass(entry: LanedEntry, date: Date): string {\n const startsHere = date.getTime() === entry.startDate.getTime();\n const endsHere = date.getTime() === entry.endDate.getTime();\n if (startsHere && endsHere) return \"segment-single\";\n if (startsHere) return \"segment-start\";\n if (endsHere) return \"segment-end\";\n return \"segment-middle\";\n }\n\n /** Current render key shared by an entry's title and body cells. */\n private _entryKey(entry: LanedEntry): string {\n return `${entry.lane}|${entry.start}|${entry.end}|${entry.label}|${entry.href ?? \"\"}`;\n }\n\n /** Toggles one interaction class on every rendered cell belonging to an entry. */\n private _setEntryInteraction(entryKey: string, className: string, active: boolean): void {\n for (const cell of this.renderRoot.querySelectorAll<HTMLElement>(\".entry-bar\")) {\n if (cell.dataset.entryKey === entryKey) {\n cell.classList.toggle(className, active);\n }\n }\n }\n\n /** Reconciles classes against the links actually hovered or focused after a render. */\n private _syncEntryInteractions(): void {\n for (const cell of this.renderRoot.querySelectorAll<HTMLElement>(\".entry-bar\")) {\n cell.classList.remove(\"entry-hovered\", \"entry-focused\");\n }\n for (const link of this.renderRoot.querySelectorAll<HTMLElement>(\".entry-link:hover\")) {\n this._setEntryInteraction(link.dataset.entryKey ?? \"\", \"entry-hovered\", true);\n }\n const activeElement = this.shadowRoot?.activeElement;\n if (activeElement instanceof HTMLElement && activeElement.matches(\".entry-link\")) {\n this._setEntryInteraction(activeElement.dataset.entryKey ?? \"\", \"entry-focused\", true);\n }\n }\n\n /** Renders a transparent full-cell link without wrapping the visible text. */\n private _renderEntryLink(entry: LanedEntry, accessibleText: string) {\n const entryKey = this._entryKey(entry);\n return entry.href\n ? html`<a\n class=\"entry-link\"\n href=${entry.href}\n aria-label=${accessibleText}\n data-entry-key=${entryKey}\n @pointerenter=${() => this._setEntryInteraction(entryKey, \"entry-hovered\", true)}\n @pointerleave=${() => this._setEntryInteraction(entryKey, \"entry-hovered\", false)}\n @focus=${() => this._setEntryInteraction(entryKey, \"entry-focused\", true)}\n @blur=${() => this._setEntryInteraction(entryKey, \"entry-focused\", false)}\n ></a>`\n : nothing;\n }\n\n /** Joins the event title, details, and visible footer for tooltips and accessible link names. */\n private _entryBodyText(entry: LanedEntry, showFooter: boolean): string {\n return [entry.label, ...(entry.details ?? []), showFooter ? entry.footer : undefined]\n .filter((line): line is string => Boolean(line))\n .join(\"\\n\");\n }\n\n /** Renders the shared details body, with the footer reserved at its bottom edge. */\n private _renderEntryBody(\n entry: LanedEntry,\n showFooter: boolean,\n detailLineClamp: number,\n showTitleFallback = false,\n ) {\n const sourceDetails = entry.details ?? [];\n const footer = showFooter ? entry.footer : undefined;\n const details =\n showTitleFallback && sourceDetails.length === 0 && !footer\n ? [entry.label]\n : sourceDetails;\n const bodyText = this._entryBodyText(entry, showFooter);\n return html`\n ${this._renderEntryLink(entry, bodyText)}\n <div class=\"entry-body\" aria-hidden=${entry.href ? \"true\" : nothing}>\n ${detailLineClamp > 0 && details.length > 0\n ? html`\n <div\n class=\"entry-details\"\n style=${`--entry-detail-lines: ${detailLineClamp}; --entry-detail-max-height: ${\n detailLineClamp * 1.15\n }em`}\n >\n ${details.map((detail) => html`<div class=\"entry-detail\">${detail}</div>`)}\n </div>\n `\n : nothing}\n ${footer ? html`<div class=\"entry-footer\" title=${footer}>${footer}</div>` : nothing}\n </div>\n `;\n }\n\n /** Renders a row-spanning body cell with whole-line detail and footer budgets. */\n private _renderEntryBodyCell(\n entry: LanedEntry,\n bodyRows: number,\n reachesEventEnd: boolean,\n showTitleFallback = false,\n ) {\n const segmentClass = reachesEventEnd ? \"segment-end\" : \"segment-middle\";\n const footerLineBudget = reachesEventEnd && entry.footer ? 1 : 0;\n const detailLineClamp = Math.max(0, bodyRows - footerLineBudget);\n const bodyText = this._entryBodyText(entry, reachesEventEnd);\n return html`\n <td\n class=\"lane-cell entry-bar entry-body-cell ${entry.color} ${segmentClass}\"\n data-entry-key=${this._entryKey(entry)}\n rowspan=${bodyRows}\n title=${entry.href ? nothing : bodyText}\n >\n ${this._renderEntryBody(entry, reachesEventEnd, detailLineClamp, showTitleFallback)}\n </td>\n `;\n }\n\n /** Renders a lane's title/body cell, skips rows covered by a body rowspan, or emits an empty spacer. */\n private _renderLaneCell(\n laned: LanedEntry[],\n lane: number,\n date: Date,\n monthStart: Date,\n monthEnd: Date,\n ) {\n const entry = this._entryFor(laned, lane, date);\n if (!entry) {\n return html`<td class=\"lane-cell empty\"></td>`;\n }\n\n const firstVisibleDay = entry.startDate > monthStart ? entry.startDate : monthStart;\n const lastVisibleDay = entry.endDate < monthEnd ? entry.endDate : monthEnd;\n const dayOffset = date.getDate() - firstVisibleDay.getDate();\n const visibleDayCount = lastVisibleDay.getDate() - firstVisibleDay.getDate() + 1;\n const isMultiDayEntry = entry.startDate.getTime() !== entry.endDate.getTime();\n const isEndingOnlyClip =\n visibleDayCount === 1 &&\n isMultiDayEntry &&\n date.getTime() === entry.endDate.getTime();\n if (isEndingOnlyClip) {\n return this._renderEntryBodyCell(entry, 1, true, true);\n }\n if (dayOffset > 1) return nothing;\n\n if (dayOffset === 1) {\n const bodyRows = visibleDayCount - 1;\n const reachesEventEnd = lastVisibleDay.getTime() === entry.endDate.getTime();\n return this._renderEntryBodyCell(entry, bodyRows, reachesEventEnd);\n }\n\n return html`\n <td\n class=\"lane-cell entry-bar entry-title-cell ${entry.color} ${this._segmentClass(entry, date)}\"\n data-entry-key=${this._entryKey(entry)}\n title=${entry.href ? nothing : entry.label}\n >\n ${this._renderEntryLink(entry, entry.label)}\n <span class=\"entry-line entry-title\" aria-hidden=${entry.href ? \"true\" : nothing}>\n ${entry.label}\n </span>\n </td>\n `;\n }\n\n protected override render() {\n const totalDays = daysInMonth(this.year, this.month);\n const monthStart = new Date(this.year, this.month - 1, 1);\n const monthEnd = new Date(this.year, this.month - 1, totalDays);\n\n const resolved = this._entryElements\n .map(readCalendarEntryElement)\n .map(resolveEntry)\n .filter((entry): entry is ResolvedCalendarEntry => entry !== null)\n .filter((entry) => overlapsRange(entry, monthStart, monthEnd));\n const { entries: laned, laneCount } = assignLanes(resolved);\n const todayIso = toIsoDate(new Date());\n const lanes = Array.from({ length: Math.max(laneCount, 1) }, (_, i) => i);\n\n return html`\n <div class=\"month\">\n <h4 class=\"month-name\">${monthName(this.month)} ${this.year}</h4>\n <table>\n <tbody>\n ${repeat(\n Array.from({ length: totalDays }, (_, i) => i + 1),\n (d) => d,\n (d) => {\n const date = new Date(this.year, this.month - 1, d);\n const dow = date.getDay();\n const weekendCls = isWeekend(date) ? \"weekend\" : \"\";\n const todayCls = toIsoDate(date) === todayIso ? \"today\" : \"\";\n return html`\n <tr class=\"day-row ${weekendCls} ${todayCls}\">\n <td class=\"day-number\">${d}</td>\n <td class=\"day-weekday\">${WEEKDAY_ABBR[dow]}</td>\n ${lanes.map((lane) => this._renderLaneCell(laned, lane, date, monthStart, monthEnd))}\n </tr>\n `;\n },\n )}\n </tbody>\n </table>\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"calendar-month\": CalendarMonth;\n }\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"chat-message.d.ts","sourceRoot":"","sources":["../src/chat-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAGrD,OAAO,oBAAoB,CAAC;AAG5B,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC1D,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAEhE;;;;;;;;;GASG;AACH,qBACa,WAAY,SAAQ,UAAU;IACzC,OAAgB,MAAM,4BAyGpB;IAEF,gEAAgE;IAC1B,IAAI,EAAE,eAAe,CAAW;IACtE,6FAA6F;IAChE,OAAO,EAAE,kBAAkB,CAAY;IACpE,kDAAkD;IACtC,MAAM,SAAM;IACxB,sEAAsE;IAC1D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5C,+FAA+F;IACnF,OAAO,SAAM;IACzB,iEAAiE;IACpC,WAAW,UAAS;IACjD,0DAA0D;IACd,SAAS,UAAS;IAE9D,OAAO,CAAC,OAAO;IAMN,MAAM,yCA8Bd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,cAAc,EAAE,WAAW,CAAC;KAC7B;CACF"}
1
+ {"version":3,"file":"chat-message.d.ts","sourceRoot":"","sources":["../src/chat-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAsB,MAAM,KAAK,CAAC;AAGrD,OAAO,oBAAoB,CAAC;AAG5B,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC1D,MAAM,MAAM,kBAAkB,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;AAEhE;;;;;;;;;GASG;AACH,qBACa,WAAY,SAAQ,UAAU;IACzC,OAAgB,MAAM,4BAmHpB;IAEF,gEAAgE;IAC1B,IAAI,EAAE,eAAe,CAAW;IACtE,6FAA6F;IAChE,OAAO,EAAE,kBAAkB,CAAY;IACpE,kDAAkD;IACtC,MAAM,SAAM;IACxB,sEAAsE;IAC1D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC5C,+FAA+F;IACnF,OAAO,SAAM;IACzB,iEAAiE;IACpC,WAAW,UAAS;IACjD,0DAA0D;IACd,SAAS,UAAS;IAE9D,OAAO,CAAC,OAAO;IAMN,MAAM,yCA8Bd;CACF;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,cAAc,EAAE,WAAW,CAAC;KAC7B;CACF"}