@santi020k/lumen-core 3.0.0 → 4.0.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 (147) hide show
  1. package/PHONE_FLAG_LICENSE.txt +21 -0
  2. package/README.md +379 -4
  3. package/THIRD_PARTY_NOTICES.md +16 -2
  4. package/dist/ai-surfaces.d.ts +25 -0
  5. package/dist/ai-surfaces.d.ts.map +1 -0
  6. package/dist/ai-surfaces.js +162 -0
  7. package/dist/amount-field.d.ts +22 -0
  8. package/dist/amount-field.d.ts.map +1 -0
  9. package/dist/amount-field.js +207 -0
  10. package/dist/attachments.d.ts +15 -0
  11. package/dist/attachments.d.ts.map +1 -0
  12. package/dist/attachments.js +123 -0
  13. package/dist/bullet-chart.d.ts +33 -0
  14. package/dist/bullet-chart.d.ts.map +1 -0
  15. package/dist/bullet-chart.js +80 -0
  16. package/dist/chart-activation.d.ts +32 -0
  17. package/dist/chart-activation.d.ts.map +1 -0
  18. package/dist/chart-activation.js +97 -0
  19. package/dist/chart-interaction.d.ts +12 -0
  20. package/dist/chart-interaction.d.ts.map +1 -0
  21. package/dist/chart-interaction.js +274 -0
  22. package/dist/chart-models.d.ts +156 -0
  23. package/dist/chart-models.d.ts.map +1 -0
  24. package/dist/chart-models.js +348 -0
  25. package/dist/chart-motion.d.ts +6 -0
  26. package/dist/chart-motion.d.ts.map +1 -0
  27. package/dist/chart-motion.js +107 -0
  28. package/dist/charts.d.ts +68 -3
  29. package/dist/charts.d.ts.map +1 -1
  30. package/dist/charts.js +328 -29
  31. package/dist/code.js +1 -1
  32. package/dist/combobox.d.ts +7 -0
  33. package/dist/combobox.d.ts.map +1 -0
  34. package/dist/combobox.js +253 -0
  35. package/dist/comparison-chart.d.ts +32 -0
  36. package/dist/comparison-chart.d.ts.map +1 -0
  37. package/dist/comparison-chart.js +64 -0
  38. package/dist/components.d.ts +210 -25
  39. package/dist/components.d.ts.map +1 -1
  40. package/dist/components.js +102 -26
  41. package/dist/dashboard.d.ts +16 -0
  42. package/dist/dashboard.d.ts.map +1 -0
  43. package/dist/dashboard.js +21 -0
  44. package/dist/data.d.ts.map +1 -1
  45. package/dist/data.js +21 -5
  46. package/dist/dates.d.ts +13 -0
  47. package/dist/dates.d.ts.map +1 -0
  48. package/dist/dates.js +37 -0
  49. package/dist/device-frame.d.ts +25 -0
  50. package/dist/device-frame.d.ts.map +1 -0
  51. package/dist/device-frame.js +50 -0
  52. package/dist/direction.d.ts +3 -0
  53. package/dist/direction.d.ts.map +1 -0
  54. package/dist/direction.js +10 -0
  55. package/dist/extended-charts.d.ts +95 -0
  56. package/dist/extended-charts.d.ts.map +1 -0
  57. package/dist/extended-charts.js +175 -0
  58. package/dist/figma.d.ts.map +1 -1
  59. package/dist/figma.js +10 -1
  60. package/dist/forms.d.ts.map +1 -1
  61. package/dist/forms.js +18 -4
  62. package/dist/icon-data.generated.d.ts +1 -1
  63. package/dist/icon-data.generated.d.ts.map +1 -1
  64. package/dist/icon-data.generated.js +1 -1
  65. package/dist/icons.js +3 -4
  66. package/dist/illustrations.generated.d.ts +1 -1
  67. package/dist/image-comparison.d.ts +14 -0
  68. package/dist/image-comparison.d.ts.map +1 -0
  69. package/dist/image-comparison.js +48 -0
  70. package/dist/index.d.ts +35 -4
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +34 -3
  73. package/dist/media-viewport.d.ts +24 -0
  74. package/dist/media-viewport.d.ts.map +1 -0
  75. package/dist/media-viewport.js +119 -0
  76. package/dist/media-workspace.d.ts +27 -0
  77. package/dist/media-workspace.d.ts.map +1 -0
  78. package/dist/media-workspace.js +83 -0
  79. package/dist/message-scroller.d.ts +14 -0
  80. package/dist/message-scroller.d.ts.map +1 -0
  81. package/dist/message-scroller.js +113 -0
  82. package/dist/motion-workflows.d.ts +24 -0
  83. package/dist/motion-workflows.d.ts.map +1 -0
  84. package/dist/motion-workflows.js +220 -0
  85. package/dist/motion.d.ts +12 -0
  86. package/dist/motion.d.ts.map +1 -0
  87. package/dist/motion.js +96 -0
  88. package/dist/native-input.d.ts +25 -0
  89. package/dist/native-input.d.ts.map +1 -0
  90. package/dist/native-input.js +188 -0
  91. package/dist/phone-flags.generated.d.ts +2 -0
  92. package/dist/phone-flags.generated.d.ts.map +1 -0
  93. package/dist/phone-flags.generated.js +263 -0
  94. package/dist/phone.d.ts +4 -0
  95. package/dist/phone.d.ts.map +1 -1
  96. package/dist/phone.js +6 -1
  97. package/dist/rich-text.d.ts +7 -0
  98. package/dist/rich-text.d.ts.map +1 -1
  99. package/dist/rich-text.js +13 -0
  100. package/dist/rive.d.ts +37 -0
  101. package/dist/rive.d.ts.map +1 -0
  102. package/dist/rive.js +129 -0
  103. package/dist/schedule.d.ts.map +1 -1
  104. package/dist/schedule.js +63 -23
  105. package/dist/tab-indicator.d.ts +3 -0
  106. package/dist/tab-indicator.d.ts.map +1 -0
  107. package/dist/tab-indicator.js +57 -0
  108. package/dist/theme-audit.d.ts +16 -0
  109. package/dist/theme-audit.d.ts.map +1 -0
  110. package/dist/theme-audit.js +57 -0
  111. package/dist/theme-builder.d.ts +7 -1
  112. package/dist/theme-builder.d.ts.map +1 -1
  113. package/dist/theme-builder.js +45 -23
  114. package/dist/theme-presets.generated.d.ts +217 -0
  115. package/dist/theme-presets.generated.d.ts.map +1 -0
  116. package/dist/theme-presets.generated.js +231 -0
  117. package/dist/theme.d.ts +11 -3
  118. package/dist/theme.d.ts.map +1 -1
  119. package/dist/theme.js +56 -6
  120. package/dist/virtual-collection.d.ts +14 -0
  121. package/dist/virtual-collection.d.ts.map +1 -0
  122. package/dist/virtual-collection.js +132 -0
  123. package/dist/virtual-list.d.ts +7 -0
  124. package/dist/virtual-list.d.ts.map +1 -0
  125. package/dist/virtual-list.js +135 -0
  126. package/dist/virtual-window.d.ts +19 -0
  127. package/dist/virtual-window.d.ts.map +1 -0
  128. package/dist/virtual-window.js +84 -0
  129. package/dist/visual-effects.d.ts +6 -0
  130. package/dist/visual-effects.d.ts.map +1 -0
  131. package/dist/visual-effects.js +44 -0
  132. package/dist/world-map-data.generated.d.ts +9 -0
  133. package/dist/world-map-data.generated.d.ts.map +1 -0
  134. package/dist/world-map-data.generated.js +240 -0
  135. package/dist/world-map-navigation.d.ts +16 -0
  136. package/dist/world-map-navigation.d.ts.map +1 -0
  137. package/dist/world-map-navigation.js +53 -0
  138. package/dist/world-map-pan.d.ts +3 -0
  139. package/dist/world-map-pan.d.ts.map +1 -0
  140. package/dist/world-map-pan.js +66 -0
  141. package/dist/world-map-zoom.d.ts +13 -0
  142. package/dist/world-map-zoom.d.ts.map +1 -0
  143. package/dist/world-map-zoom.js +61 -0
  144. package/dist/world-map.d.ts +71 -0
  145. package/dist/world-map.d.ts.map +1 -0
  146. package/dist/world-map.js +143 -0
  147. package/package.json +51 -4
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 Panayiotis Lipiridis
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
6
+ this software and associated documentation files (the "Software"), to deal in
7
+ the Software without restriction, including without limitation the rights to
8
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
9
+ of the Software, and to permit persons to whom the Software is furnished to do
10
+ so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,4 +1,66 @@
1
- # @santi020k/lumen-core
1
+ <p align="center">
2
+ <a href="https://lumen.santi020k.com">
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/santi020k/lumen/main/docs/assets/readme/package-dark.svg">
5
+ <img src="https://raw.githubusercontent.com/santi020k/lumen/main/docs/assets/readme/package-light.svg" alt="Lumen UI — Web. Native. Thoughtfully connected." width="1200" height="184">
6
+ </picture>
7
+ </a>
8
+ </p>
9
+
10
+ <h1 align="center">Lumen UI · Core</h1>
11
+
12
+ <p align="center">Shared contracts · Metadata · Framework-neutral helpers</p>
13
+
14
+ <p align="center">
15
+ <a href="https://www.npmjs.com/package/@santi020k/lumen-core"><img src="https://img.shields.io/npm/v/@santi020k/lumen-core?style=flat-square&color=0369a0" alt="npm version"></a>
16
+ <a href="https://github.com/santi020k/lumen/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-13967e?style=flat-square" alt="MIT license"></a>
17
+ </p>
18
+
19
+ <p align="center">
20
+ <a href="https://lumen.santi020k.com/docs/foundations">Documentation</a>
21
+ ·
22
+ <a href="https://www.npmjs.com/package/@santi020k/lumen-core">npm</a>
23
+ ·
24
+ <a href="https://github.com/santi020k/lumen/tree/main/packages/core">Source</a>
25
+ ·
26
+ <a href="https://github.com/santi020k/lumen/issues">Issues</a>
27
+ </p>
28
+
29
+ **Package:** `@santi020k/lumen-core`
30
+
31
+ **On this page:** [Install](#install) · [Quick start](#quick-start) · [Appearance presets](#appearance-presets) · [Resources](#resources)
32
+
33
+ <details>
34
+ <summary>Browse all sections</summary>
35
+
36
+ - [Install](#install)
37
+ - [Quick start](#quick-start)
38
+ - [Data view state](#data-view-state)
39
+ - [Schedule helpers](#schedule-helpers)
40
+ - [Appearance presets](#appearance-presets)
41
+ - [Language Helpers](#language-helpers)
42
+ - [Date Helpers](#date-helpers)
43
+ - [Chart Helpers](#chart-helpers)
44
+ - [Phone Helpers](#phone-helpers)
45
+ - [Icon Credits](#icon-credits)
46
+ - [Theme Builder Helpers](#theme-builder-helpers)
47
+ - [Figma and Design Tokens](#figma-and-design-tokens)
48
+ - [Static interface icon data](#static-interface-icon-data)
49
+ - [Consumer diagnostics and exact amounts](#consumer-diagnostics-and-exact-amounts)
50
+ - [Combobox DOM controller](#combobox-dom-controller)
51
+ - [Virtual collections and direction](#virtual-collections-and-direction)
52
+ - [Exact localized input drafts](#exact-localized-input-drafts)
53
+ - [Attachment preview state](#attachment-preview-state)
54
+ - [Chart datum activation](#chart-datum-activation)
55
+ - [Dashboard contracts](#dashboard-contracts)
56
+ - [Extended chart models](#extended-chart-models)
57
+ - [Optional visual integrations](#optional-visual-integrations)
58
+ - [Presence motion](#presence-motion)
59
+ - [World map](#world-map)
60
+ - [Studio media workspace](#studio-media-workspace)
61
+ - [Resources](#resources)
62
+
63
+ </details>
2
64
 
3
65
  Shared metadata, token constants, and tiny utilities used by the Lumen package family.
4
66
 
@@ -16,6 +78,59 @@ Cross-platform foundations originate in `tokens/lumen.tokens.json` and are publi
16
78
  numeric spacing, radius, typography, duration, easing, and elevation values. The legacy
17
79
  `lumenColors` export retains CSS-ready HSL values.
18
80
 
81
+ ## Install
82
+
83
+ Install core directly when building framework-neutral tooling or a custom adapter:
84
+
85
+ ```bash
86
+ pnpm add @santi020k/lumen-core
87
+ ```
88
+
89
+ Core provides data and helpers; it does not register elements, render components, or load CSS.
90
+ Use documented subpath exports such as `/charts`, `/phone`, and `/icon-data` for focused imports.
91
+ Image-comparison helpers use `/image-comparison`; DOM windowing uses
92
+ `/virtual-list`, and data-renderer window calculations use `/virtual-window`.
93
+
94
+ ## Quick start
95
+
96
+ Read semantic foundations through the focused token entry:
97
+
98
+ ```ts
99
+ import { lumenColors } from '@santi020k/lumen-core/tokens'
100
+
101
+ const brandChannels = lumenColors.brand
102
+ ```
103
+
104
+ `lumenColors` contains CSS-ready HSL channels. For portable JSON and native generated palettes,
105
+ use the [design tokens package](https://github.com/santi020k/lumen/blob/main/packages/tokens/README.md).
106
+
107
+ ## Data view state
108
+
109
+ `serializeDataViewState` and `parseDataViewState` preserve named filters, including names that
110
+ match built-in object properties, as ordinary own properties. Repeated filter parameters use
111
+ the last value. `createDataViewRequestUrl` and `createDataViewServerRequest` append state to
112
+ an endpoint's query before its fragment, preserving existing query parameters and fragment text.
113
+ Import these helpers from the root or `@santi020k/lumen-core/data`.
114
+
115
+ ## Schedule helpers
116
+
117
+ `canPlaceScheduleEvent` rejects malformed or reversed candidate intervals, including in an empty
118
+ schedule. `scheduleEventsOverlap` conservatively treats an invalid interval as a conflict with
119
+ a different event sharing its resource; distinct resources and identical event IDs retain their
120
+ existing behavior. Adjacent valid intervals remain available.
121
+
122
+ `resizeScheduleEvent` and `expandRecurringScheduleEvent` reject invalid date-times with `TypeError`.
123
+ Recurrence advances UTC calendar days and preserves UTC time-of-day independently of the host time zone. Applications own civil-time recurrence policies and DST conversion.
124
+
125
+ Invalid bounds, non-finite snapping/recurrence options, unsupported resulting date-times, and
126
+ non-integer or negative recurrence counts produce `RangeError`. Applications own validation and
127
+ recovery feedback. `parseScheduleEvents` preserves structurally valid records with malformed
128
+ date-times so applications can repair the original data; these helpers do not rewrite storage.
129
+
130
+ ## Appearance presets
131
+
132
+ Use `createThemePreset('studio', { scheme: 'dark', overrides: { 'ui-radius': '0.75rem' } })` for a named starting point. Default, Studio and Glass share the [appearance contract](https://github.com/santi020k/lumen/blob/main/docs/appearance-presets.md).
133
+
19
134
  ## Language Helpers
20
135
 
21
136
  The root entry exports the shared locale contract used by the Astro, React, and Elements language
@@ -45,16 +160,48 @@ const label = formatLumenLanguageLabel(
45
160
  )
46
161
  ```
47
162
 
163
+ ## Date Helpers
164
+
165
+ Calendar adapters share `parseLumenDate`, `isLumenDateBoundsValid`, and
166
+ `isLumenDateRangeValid` from the core root entry. They accept complete Gregorian
167
+ `YYYY-MM-DD` dates in years 0001–9999, reject overflow dates, and require ordered,
168
+ inclusive bounds. `resolveLumenDateLocale` normalizes an explicit locale or the
169
+ browser locale, falling back to English for invalid locale tags.
170
+ `resolveLumenDateLabels` supplies English and Spanish navigation, picker, and
171
+ invalid-range defaults through the `LumenDateLabels` contract. Components allow
172
+ label overrides for other languages; pass an explicit locale during SSR.
173
+
174
+ `isLumenDateRangeValid` accepts unknown restored data and returns `false` for a missing record
175
+ or non-string range fields instead of dereferencing malformed input.
176
+
48
177
  ## Chart Helpers
49
178
 
179
+ The package root also exports `createLumenLineChartModel`, `createLumenWaterfallGeometry`,
180
+ `createLumenHistogramGeometry`, and `createLumenHeatmapModel`. These pure models share web geometry,
181
+ validation, ticks, and annotations. The optional `createLumenChartInteractionController` owns only
182
+ DOM listeners and cursor/legend state; call `destroy()` when removing its surface.
183
+ Line chart models ignore malformed annotation entries and containers before reading overlay fields.
184
+ When annotation IDs repeat, the first valid entry wins so overlay identities stay unique.
185
+ Destroying a chart controller restores series marks, inspection values, and legend pressed state
186
+ so rebinding starts with all series visible.
187
+ Waterfall and histogram geometry accept arrays of unknown decoded rows, validate their complete
188
+ shape before accumulation or sorting, and return `valid: false` with empty marks when a row is
189
+ malformed. Typed component props continue to use `LumenWaterfallDatum` and `LumenHistogramBin`.
190
+ `normalizeLumenHeatmapData` validates decoded cell arrays before adapters read coordinates or
191
+ format labels. It returns an empty array when any row has malformed coordinates, measurement
192
+ types, labels, identity, or tone. Heatmap geometry and models use it internally. Explicit `null`
193
+ and non-finite numeric measurements retain the existing missing-cell behavior; numeric coordinates
194
+ must be finite.
195
+
50
196
  `@santi020k/lumen-core/charts` exports the shared `LumenChartSeries` contract plus deterministic
51
197
  domain, tick, scaling, line/area, grouped/stacked bar, and pie/donut geometry helpers. They render
52
198
  no DOM and perform no statistical analysis; framework packages use them to keep chart output
53
- aligned.
199
+ aligned. Linear x coordinates ignore blank strings rather than treating them as zero.
54
200
 
55
201
  ```ts
56
202
  import {
57
203
  createLumenLineGeometry,
204
+ getLumenChartAxisPadding,
58
205
  type LumenChartSeries
59
206
  } from '@santi020k/lumen-core/charts'
60
207
 
@@ -64,9 +211,23 @@ const series: LumenChartSeries = {
64
211
  data: [{ x: 'Mon', y: 42 }, { x: 'Tue', y: 68 }]
65
212
  }
66
213
 
67
- createLumenLineGeometry(series.data)
214
+ const valueLabels = ['$0', '$68,000']
215
+ const paddingLeft = getLumenChartAxisPadding(valueLabels)
216
+
217
+ createLumenLineGeometry(series.data, {
218
+ paddingBottom: 24,
219
+ paddingLeft,
220
+ paddingRight: 16,
221
+ paddingTop: 16
222
+ })
68
223
  ```
69
224
 
225
+ Use `getLumenChartAxisPadding` when formatted value-axis labels need more than the default inset.
226
+ It estimates proportional and wide Unicode glyphs during server rendering, honors an optional
227
+ minimum, and caps the result at 240 so labels cannot consume the complete plot. The line geometry
228
+ helper accepts `paddingTop`, `paddingRight`, `paddingBottom`, and `paddingLeft` to reserve each edge
229
+ independently; unspecified edges fall back to `padding`.
230
+
70
231
  ## Phone Helpers
71
232
 
72
233
  `@santi020k/lumen-core/phone` provides localized country metadata, supplementary flag labels,
@@ -74,6 +235,8 @@ as-you-type formatting, validation, pasted international-number detection, and E
74
235
  web and React Native adapters.
75
236
 
76
237
  ```ts
238
+ import { getLumenPhoneCountry, resolveLumenPhoneNumber } from '@santi020k/lumen-core/phone'
239
+
77
240
  const colombia = getLumenPhoneCountry('CO', { locale: 'en-US' })
78
241
  if (!colombia) throw new Error('Missing Colombia metadata')
79
242
 
@@ -83,6 +246,8 @@ const phone = resolveLumenPhoneNumber(colombia, '6015550123')
83
246
  It also exports the Lucide-backed icon map (`lumenIcons`, `lumenIconNames`) and helpers such as
84
247
  `renderLumenIconSvg` so framework adapters can render icons by name.
85
248
 
249
+ Icon resolution only accepts dictionary-owned names; inherited object properties are rejected.
250
+
86
251
  ## Icon Credits
87
252
 
88
253
  Icons are provided by [Lucide](https://lucide.dev/) and its open-source contributors. Lucide is
@@ -147,4 +312,214 @@ React consumers can import both the renderer and definitions from
147
312
  `@santi020k/lumen-react/icons`. Existing `getLumenIcon`, runtime names, and registered icon packs
148
313
  remain supported through the original API. The interface selection in `icons/lumen.icons.json`
149
314
  controls the generated exports; run `pnpm run generate:platform-icons` after catalog changes.
150
- See [consumer UI recipes](../../docs/consumer-ui-recipes.md#static-react-icons).
315
+ See [consumer UI recipes](https://github.com/santi020k/lumen/blob/main/docs/consumer-ui-recipes.md#static-react-icons).
316
+
317
+ ## Consumer diagnostics and exact amounts
318
+
319
+ `auditLumenTheme` requires every semantic color mapping and checks normal-text contrast for
320
+ resolved opaque HSL channels. `inspectLumenTheme(element)` reads computed mappings in each
321
+ representative light, dark and nested scope. Unsupported color syntax produces a finding rather
322
+ than an assumed pass; these checks supplement rendered accessibility verification.
323
+
324
+ `formatLumenAmountDraft`, `parseLumenAmountDraft` and `getLumenAmountValue` preserve exact ASCII
325
+ decimal strings across localized display and editing. Invalid locale tags fall back to `en-US`
326
+ consistently in server rendering, parsing and browser controllers. Call the amount controller’s
327
+ `refresh()` after moving it to a different document or shadow root; this rebinds native form resets
328
+ without replacing its draft. The shared amount and message-scroller DOM controllers power the web
329
+ adapters. Currency policy and message state remain consumer-owned.
330
+
331
+ ## Combobox DOM controller
332
+
333
+ `createLumenComboboxController(root)` enhances a client-side root containing an
334
+ `input[role="combobox"]` and a `[role="listbox"]` with `[role="option"]` children.
335
+ It preserves editing focus, observes option changes and supports delegated selection. It returns
336
+ `close()` and `destroy()`; call `destroy()` when the owner disconnects. Astro and Elements manage
337
+ that lifecycle automatically. React uses its state-driven component with the same keyboard contract.
338
+ An accepted native form reset closes options, clears the active descendant, and refilters against
339
+ the restored input value without emitting change events. Canceled resets preserve editing state;
340
+ `destroy()` cancels pending reset work. Pointer selection cancels native option-button submission.
341
+ Filtering preserves application-hidden options; cleanup restores options hidden by the filter.
342
+ The controller respects disabled fieldset ancestors and uses the input's current form association
343
+ when handling resets.
344
+
345
+ The mounted VirtualList controller supports roots and rows created in another document, including
346
+ same-origin iframe documents.
347
+ Data-mode collections preserve iframe keyboard focus across distant scrolling and keyed updates,
348
+ and return focus to the list when the focused record is removed.
349
+
350
+ ## Virtual collections and direction
351
+
352
+ `createLumenVirtualCollectionController(root, { items, getKey, renderItem, itemSize, overscan })`
353
+ owns an empty data-mode VirtualList root. It mounts only visible rows and focused neighbors, retains
354
+ stable keyed wrappers, and returns `update(items)` and `destroy()`. Declare data mode before the
355
+ Astro or Elements runtime initializes. See [data rendering](https://github.com/santi020k/lumen/blob/main/docs/virtual-list-data.md) for
356
+ setup, state ownership and lifecycle examples.
357
+
358
+ `getLumenVirtualWindow` calculates a fixed-height window with optional disjoint focus retention.
359
+ `observeLumenVirtualWindow` observes scroll, resize and focus; its handle provides `update()` and
360
+ `destroy()`. Applications using these lower-level helpers own row rendering and cleanup.
361
+ Data-mode controllers also preserve focus and reusable keyed content in same-origin iframe
362
+ documents, including elements adopted from another document. Range events and resize observation
363
+ use the root's document.
364
+
365
+ `getLumenDirectionalKey(element, key)` resolves the element's current inherited CSS direction and
366
+ swaps horizontal arrows in RTL. Other keys are unchanged. Web adapters use it for visual keyboard
367
+ navigation; native range inputs retain browser-owned behavior.
368
+
369
+ ## Exact localized input drafts
370
+
371
+ `parseLumenDecimalDraft(value, locale)` distinguishes empty, incomplete, invalid and valid decimal
372
+ input. `isLumenDecimalInBounds(value, { locale, min, max, step })` validates complete values;
373
+ `stepLumenDecimalDraft(value, direction, options)` performs exact steps and inclusive clamping without
374
+ floating-point conversion. Bounds and steps use ASCII decimal strings; drafts use localized decimal
375
+ separators, the locale's numbering-system digits, and Unicode decimal digits. This includes Chinese
376
+ decimal numerals (`hanidec`), so formatted steps remain editable on subsequent steps.
377
+ Grouping, exponents, whitespace and inputs exceeding 128
378
+ characters are rejected. Empty drafts stay distinct from zero; unfinished drafts cannot step.
379
+ Malformed locale tags safely use English decimal symbols.
380
+ Applications own units, currency policy, required validation and submission serialization.
381
+
382
+ `normalizeLumenNumericOTP(proposal, length)` normalizes Unicode decimal digits, whitespace and hyphens
383
+ into ASCII, rejects unrelated text and excess digits, and bounds input to 128 characters. Length must
384
+ be 1–12. `LumenTimeSelection`, `isLumenTimeSelection` and `isLumenTimeInBounds` describe wall-clock
385
+ hours/minutes with inclusive same-day bounds, leaving dates and time zones to the application.
386
+ ## Attachment preview state
387
+
388
+ `resolveLumenAttachmentPreviewState` resolves explicit fallback states, unsupported MIME types,
389
+ and image failures. `createLumenAttachmentPreviewController` enhances the documented DOM child
390
+ contract with safe state events and lifecycle cleanup. Use the framework components for product UI;
391
+ see the [attachment recipe](https://github.com/santi020k/lumen/blob/main/docs/consumer-ui-recipes.md#attachment-previews-and-file-lists).
392
+
393
+ Non-string source or MIME metadata resolves to `unavailable`; explicit loading and error states
394
+ still take precedence.
395
+
396
+ ## Chart datum activation
397
+
398
+ `createLumenChartDatumActivation(seriesId, datum)`, `createLumenHeatmapDatumActivation(datum)`,
399
+ and `createLumenRangeDatumActivation(datum)` return a validated `LumenChartDatumActivationDetail`
400
+ or `null` for an unavailable observation. The discriminated payload preserves raw axes and optional
401
+ datum IDs. `parseLumenChartDatumActivation(unknown)` validates event data and removes unrelated
402
+ fields. These helpers are also available from `@santi020k/lumen-core/charts`.
403
+
404
+ For custom browser charts, `createLumenChartActivationController(root)` delegates clicks from
405
+ `[data-ui-chart-datum]` descendants owned by a `[data-ui-chart-activation]` root. Each target's
406
+ attribute contains a JSON payload from the builders. Use native buttons with descriptive labels
407
+ as keyboard equivalents for decorative SVG marks; the controller does not create that UI.
408
+ It emits the bubbling, composed `ui:chart-datum-activate` event and returns `destroy()` for cleanup.
409
+ Applications own navigation, filtering, detail views, and server authorization.
410
+
411
+ ## Dashboard contracts
412
+
413
+ `LumenChangeSummaryItem` carries explicit display values and caller-owned changed state;
414
+ `LumenActiveFilter` identifies an active criterion. `readLumenChangeSummaryItems` and
415
+ `readLumenActiveFilters` validate unknown input, reject duplicate/empty IDs, and copy records.
416
+
417
+ Scatter geometry supports positive logarithmic X coordinates, explicit domains, and shared
418
+ reference projection. `createLumenScatterReferences`, `scaleLumenScatterX`, and
419
+ `getLumenScatterXTicks` use the same coordinate contract as `createLumenScatterGeometry`.
420
+ See [consumer UI recipes](https://github.com/santi020k/lumen/blob/main/docs/consumer-ui-recipes.md) for application ownership boundaries.
421
+
422
+ ## Extended chart models
423
+
424
+ `createLumenCalendarHeatmapGeometry`, `createLumenFunnelGeometry`, and
425
+ `createLumenBoxPlotGeometry` validate complete datasets and provide normalized geometry.
426
+ Sparse datasets and sparse box-plot outlier arrays are invalid, including empty array slots.
427
+ Comparison chart geometry follows the same rule. Use explicit `null` measurements for missing
428
+ observations; invalid datasets return no plotted rows or cells.
429
+ See [data visualization](https://github.com/santi020k/lumen/blob/main/docs/data-visualization.md) for date-only identities, ordered
430
+ stages, precomputed quartiles, missing values, and domain rules.
431
+
432
+ `isLumenTimeSelection` narrows unknown decoded values to valid same-day wall-clock selections.
433
+ `isLumenTimeInBounds` returns false for malformed selections and preserves explicit bounds validation.
434
+
435
+ ## Optional visual integrations
436
+
437
+ Coordinated DOM motion, chart continuity, safe citation URLs, and prompt/approval controllers are
438
+ exported from the main package without an animation SDK. See [visual interactions](https://github.com/santi020k/lumen/blob/main/docs/visual-interactions.md).
439
+ The optional `@santi020k/lumen-core/rive` entry requires the optional peer `@rive-app/canvas@^2.44.0`.
440
+ It owns playback, data bindings, reduced motion, visibility, and cleanup for a consumer-owned asset.
441
+ ## Presence motion
442
+
443
+ `animateLumenPresence(element, options)` animates a mounted DOM reference using the browser's Web
444
+ Animations API. It is also exported from `@santi020k/lumen`. No animation dependency is required.
445
+
446
+ ```ts
447
+ import { animateLumenPresence } from '@santi020k/lumen-core'
448
+
449
+ const controller = new AbortController()
450
+ await animateLumenPresence(element, {
451
+ duration: 'standard',
452
+ preset: 'slide-up',
453
+ signal: controller.signal
454
+ })
455
+
456
+ // Before exiting, move focus out of the item and prevent further interaction.
457
+ element.inert = true
458
+ const result = await animateLumenPresence(element, {
459
+ phase: 'exit',
460
+ preset: 'fade',
461
+ signal: controller.signal
462
+ })
463
+ if (result !== 'cancelled') element.remove()
464
+ else element.inert = false
465
+ ```
466
+
467
+ Presets are `fade`, `slide-up`, and `scale`. Durations are `fast`, `standard`, and `slow`; the helper
468
+ reads the matching `--ui-duration-fast`, `--ui-duration`, or `--ui-duration-slow` and
469
+ `--ui-ease-emphasized` CSS tokens, with shared-token fallbacks. Existing transforms and opacity are
470
+ preserved. Use a wrapper when another animation already owns those properties.
471
+
472
+ The promise resolves to `finished`, `cancelled`, or `skipped`. Reduced motion, zero duration,
473
+ detached elements, and missing browser animation support skip the effect. Abort on unmount or when
474
+ an operation becomes stale. A new presence request cancels the previous one on the same element.
475
+ System reduced-motion changes cancel a running effect and resolve it as `skipped`. DOM removal,
476
+ framework state, focus restoration, inertness, and announcements belong to the consumer; an exit
477
+ animation does not hide or remove the element itself. Unexpected animation failures reject the
478
+ promise and should use the application's error handling.
479
+
480
+ Use `data-ui-motion="reduce"` on a container to skip new presence requests and, with the optional
481
+ stylesheet, disable descendant CSS motion. Abort existing requests when changing this local preference. An application must never
482
+ override the user's system reduced-motion preference to force animations.
483
+
484
+ Import `@santi020k/lumen/styles/motion.css` alongside the base stylesheet to opt into native
485
+ disclosure height transitions and the CSS reduction scope. This small optional stylesheet works
486
+ with Astro, React, and Elements and keeps those effects out of the default stylesheet. The presence
487
+ helper's system and local reduced-motion checks work without this CSS import.
488
+
489
+ When using Tailwind, import Lumen's layer order before either stylesheet:
490
+
491
+ ```css
492
+ @import "@santi020k/lumen/layers.css";
493
+ @import "tailwindcss";
494
+ @import "@santi020k/lumen/styles.css";
495
+ @import "@santi020k/lumen/styles/motion.css";
496
+ ```
497
+
498
+ ## World map
499
+
500
+ WorldMap supports highlighted countries, location markers, dotted or solid styles, country selection,
501
+ and theme customization. Use `initialView="highlighted"` (Elements: `initial-view`) to start with a
502
+ regional view. Zoom toward the cursor with Ctrl/Cmd-scroll, or fit highlighted countries using the
503
+ map controls. Import geography explicitly from
504
+ `@santi020k/lumen-core/world-map-data`; it is excluded from root exports. See the
505
+ [WorldMap usage guide](https://github.com/santi020k/lumen/blob/main/docs/world-map.md) for adapter examples, events, localization,
506
+ accessibility, and customization.
507
+
508
+ ## Studio media workspace
509
+
510
+ Compose MediaViewport, MediaThumbnail, MediaFilmstrip and ImageComparison modes with the
511
+ [Studio media workspace recipes](https://github.com/santi020k/lumen/blob/main/docs/studio-media-workspaces.md). Applications retain
512
+ media loading, selection, adjustment algorithms, processing, export and persistence.
513
+
514
+ ## Resources
515
+
516
+ | Guide | What you will find |
517
+ | --- | --- |
518
+ | [Cross-platform architecture](https://github.com/santi020k/lumen/blob/main/docs/cross-platform.md) | Shared foundations, adapter boundaries, and support tiers. |
519
+ | [Data visualization](https://github.com/santi020k/lumen/blob/main/docs/data-visualization.md) | Data visualization guidance and examples. |
520
+ | [Figma token export](https://github.com/santi020k/lumen/blob/main/docs/figma.md) | Variables, token export, and Code Connect workflows. |
521
+ | [Contributing](https://github.com/santi020k/lumen/blob/main/CONTRIBUTING.md) | Setup, checks, and contribution workflow. |
522
+ | [Release history](https://github.com/santi020k/lumen/releases) | Published releases and version notes. |
523
+
524
+ Part of [Lumen UI](https://lumen.santi020k.com), created by [Santiago Molina](https://santi020k.com).
525
+ Licensed under [MIT](https://github.com/santi020k/lumen/blob/main/LICENSE); third-party artwork retains its own notices.
@@ -1,7 +1,21 @@
1
1
  # Third-Party Notices
2
2
 
3
- `@santi020k/lumen-core` uses libphonenumber-js and the Lucide icon library. The following notices
4
- are reproduced from their licenses.
3
+ `@santi020k/lumen-core` uses libphonenumber-js, the Lucide icon library, and Natural Earth map data.
4
+ The following notices are reproduced from their licenses.
5
+
6
+ ## Natural Earth
7
+
8
+ The `@santi020k/lumen-core/world-map-data` country geometry is generated from
9
+ [Natural Earth](https://www.naturalearthdata.com/) 1:50m Cultural Vectors, Admin 0 Countries.
10
+
11
+ Per Natural Earth's [terms of use](https://www.naturalearthdata.com/about/terms-of-use/):
12
+
13
+ Natural Earth map data is public domain and may be modified and redistributed without permission
14
+ or required attribution.
15
+
16
+ See [`maps/README.md`](../../maps/README.md) for the exact source release, checksum, retrieval
17
+ date, projection, and precision notes, and `scripts/import-natural-earth-world-map.mjs` for the
18
+ reproducible import step.
5
19
 
6
20
  ## libphonenumber-js
7
21
 
@@ -0,0 +1,25 @@
1
+ export type LumenStreamStatus = 'idle' | 'streaming' | 'complete' | 'error' | 'canceled';
2
+ export type LumenToolStatus = 'queued' | 'running' | 'success' | 'error' | 'canceled';
3
+ export type LumenApprovalStatus = 'pending' | 'approved' | 'rejected';
4
+ export interface LumenPromptSubmitDetail {
5
+ text: string;
6
+ }
7
+ export interface LumenApprovalResponseDetail {
8
+ requestId: string;
9
+ response: 'approve' | 'reject';
10
+ }
11
+ export declare const readLumenPromptSubmitDetail: (value: unknown) => LumenPromptSubmitDetail | undefined;
12
+ export declare const readLumenApprovalResponseDetail: (value: unknown) => LumenApprovalResponseDetail | undefined;
13
+ export declare const normalizeLumenPromptLimit: (value: unknown) => number;
14
+ export declare const canSubmitLumenPrompt: (text: string, limit?: number) => boolean;
15
+ /** Citations accept safe web destinations and local absolute paths, never executable schemes. */
16
+ export declare const resolveLumenCitationHref: (value: unknown) => string | undefined;
17
+ export interface LumenPromptComposerController {
18
+ destroy(): void;
19
+ sync(): void;
20
+ }
21
+ /** Bind an event bridge. A supplied native action keeps its normal POST behavior. */
22
+ export declare const createLumenPromptComposerController: (root: HTMLElement) => LumenPromptComposerController;
23
+ /** This event requests a decision; the application must still authorize the actual operation. */
24
+ export declare const bindLumenApprovalCard: (root: HTMLElement) => (() => void);
25
+ //# sourceMappingURL=ai-surfaces.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-surfaces.d.ts","sourceRoot":"","sources":["../src/ai-surfaces.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,WAAW,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAA;AACxF,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAA;AACrF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,CAAA;AAErE,MAAM,WAAW,uBAAuB;IAAG,IAAI,EAAE,MAAM,CAAA;CAAE;AACzD,MAAM,WAAW,2BAA2B;IAAG,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,SAAS,GAAG,QAAQ,CAAA;CAAE;AAElG,eAAO,MAAM,2BAA2B,GAAI,OAAO,OAAO,KAAG,uBAAuB,GAAG,SAItF,CAAA;AAED,eAAO,MAAM,+BAA+B,GAAI,OAAO,OAAO,KAAG,2BAA2B,GAAG,SAM9F,CAAA;AAED,eAAO,MAAM,yBAAyB,GAAI,OAAO,OAAO,KAAG,MAI1D,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAI,MAAM,MAAM,EAAE,cAAY,KAAG,OAEjE,CAAA;AAwBD,iGAAiG;AACjG,eAAO,MAAM,wBAAwB,GAAI,OAAO,OAAO,KAAG,MAAM,GAAG,SAQlE,CAAA;AAKD,MAAM,WAAW,6BAA6B;IAC5C,OAAO,IAAI,IAAI,CAAA;IAEf,IAAI,IAAI,IAAI,CAAA;CACb;AAED,qFAAqF;AACrF,eAAO,MAAM,mCAAmC,GAAI,MAAM,WAAW,KAAG,6BA2GvE,CAAA;AAED,iGAAiG;AACjG,eAAO,MAAM,qBAAqB,GAAI,MAAM,WAAW,KAAG,CAAC,MAAM,IAAI,CA2CpE,CAAA"}