@santi020k/lumen-elements 1.7.0-rc.0 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -2
- package/bin/lumen.mjs +2 -0
- package/dist/components/badge.d.ts +21 -0
- package/dist/components/badge.d.ts.map +1 -0
- package/dist/components/badge.js +20 -0
- package/dist/components/button.d.ts +38 -0
- package/dist/components/button.d.ts.map +1 -0
- package/dist/components/button.js +35 -0
- package/dist/components/card.d.ts +25 -0
- package/dist/components/card.d.ts.map +1 -0
- package/dist/components/card.js +23 -0
- package/dist/components/combobox.d.ts +23 -0
- package/dist/components/combobox.d.ts.map +1 -0
- package/dist/components/combobox.js +138 -0
- package/dist/components/foundations.d.ts +161 -0
- package/dist/components/foundations.d.ts.map +1 -0
- package/dist/components/foundations.js +173 -0
- package/dist/define.d.ts +167 -181
- package/dist/define.d.ts.map +1 -1
- package/dist/define.js +1 -1
- package/dist/element-base.d.ts +25 -0
- package/dist/element-base.d.ts.map +1 -0
- package/dist/element-base.js +60 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/package.json +31 -3
- package/styles/critical.css +2054 -0
package/README.md
CHANGED
|
@@ -10,12 +10,23 @@ This package registers standards-based custom elements for the shared Lumen prim
|
|
|
10
10
|
pnpm add @santi020k/lumen-elements
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
+
The adapter also exposes Lumen's discovery and diagnostics CLI:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm exec lumen show Tabs
|
|
17
|
+
pnpm exec lumen doctor
|
|
18
|
+
```
|
|
19
|
+
|
|
13
20
|
Load the shared stylesheet once from your app entry or global CSS.
|
|
14
21
|
|
|
15
22
|
```css
|
|
16
23
|
@import "@santi020k/lumen-elements/styles.css";
|
|
17
24
|
```
|
|
18
25
|
|
|
26
|
+
Pair granular registrations with `@santi020k/lumen-elements/styles/critical.css` when the product
|
|
27
|
+
uses only the essential forms, feedback, tabs, dialogs, calendar, and data-table surface. Use the
|
|
28
|
+
complete stylesheet for the full element catalog.
|
|
29
|
+
|
|
19
30
|
The stylesheet defaults `--ui-font` to `"Montserrat", "Avenir Next", "Segoe UI", sans-serif`.
|
|
20
31
|
It declares the family stack but does not bundle or load font files. Load Montserrat once through
|
|
21
32
|
your preferred delivery path, or override `--ui-font` in application CSS.
|
|
@@ -40,6 +51,52 @@ independently from the document registry.
|
|
|
40
51
|
</lumen-card>
|
|
41
52
|
```
|
|
42
53
|
|
|
54
|
+
To limit registration to the tags a scoped surface owns, pass their catalog names before an
|
|
55
|
+
optional custom registry:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { defineLumenElements } from '@santi020k/lumen-elements/define'
|
|
59
|
+
|
|
60
|
+
defineLumenElements(['Card', 'Input', 'Button'])
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
The component-name list is typed, duplicate names are ignored, already-registered tags are
|
|
64
|
+
preserved, and omitting it retains complete-catalog registration. This controls registry scope, but
|
|
65
|
+
the `define` module still contains the complete implementation.
|
|
66
|
+
|
|
67
|
+
For a small surface that uses only Badge, Button, Card, and Combobox, import their implementation-level
|
|
68
|
+
entrypoints instead:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { defineLumenBadge } from '@santi020k/lumen-elements/components/badge'
|
|
72
|
+
import { defineLumenButton } from '@santi020k/lumen-elements/components/button'
|
|
73
|
+
import { defineLumenCard } from '@santi020k/lumen-elements/components/card'
|
|
74
|
+
import { defineLumenCombobox } from '@santi020k/lumen-elements/components/combobox'
|
|
75
|
+
|
|
76
|
+
defineLumenBadge()
|
|
77
|
+
defineLumenButton()
|
|
78
|
+
defineLumenCard()
|
|
79
|
+
defineLumenCombobox()
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Each function accepts an optional custom-element registry, is idempotent, and registers the exact
|
|
83
|
+
constructor used by the complete catalog. The Combobox entrypoint includes its filtering, keyboard,
|
|
84
|
+
selection, dismissal, and focus behavior without importing the complete catalog. Other components
|
|
85
|
+
still use `defineLumenElements`; do not replace the full entrypoint when the application needs a
|
|
86
|
+
behavior-backed element that does not yet have a granular module.
|
|
87
|
+
|
|
88
|
+
Foundation-only pages can register fifteen layout, composition, and accessibility elements as one
|
|
89
|
+
small implementation-level bundle:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
import { defineLumenFoundations } from '@santi020k/lumen-elements/components/foundations'
|
|
93
|
+
|
|
94
|
+
defineLumenFoundations()
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
This bundle contains the Card compound parts, Container, Direction, Grid, Label, Separator,
|
|
98
|
+
Skeleton, Spinner, Stack, Typography, and VisuallyHidden. It does not import the complete catalog.
|
|
99
|
+
|
|
43
100
|
`lumen-phone-input` can generate its complete country and telephone controls. It exposes `value`,
|
|
44
101
|
`valid`, and `e164`, and emits `ui:phone-change` with the normalized phone model. Country names and
|
|
45
102
|
calling codes remain visible so the flag is never the only identifier.
|
|
@@ -98,8 +155,7 @@ internal native control provides the same contract when `ElementInternals` is un
|
|
|
98
155
|
```
|
|
99
156
|
|
|
100
157
|
`lumen-input` forwards the numeric `size` attribute to its internal native input. Use
|
|
101
|
-
`visual-size="sm"` or `visual-size="lg"` for presentation.
|
|
102
|
-
remains available for incremental migrations.
|
|
158
|
+
`visual-size="sm"` or `visual-size="lg"` for presentation.
|
|
103
159
|
|
|
104
160
|
```html
|
|
105
161
|
<lumen-input name="code" size="12" visual-size="sm"></lumen-input>
|
|
@@ -232,6 +288,8 @@ their registered custom elements; no Astro runtime or host controller is require
|
|
|
232
288
|
Rich text controls may provide `data-ui-editor-value` for commands such as `formatBlock` and
|
|
233
289
|
`createLink`; editable surfaces emit `ui:editor-change` with both HTML and plain text, support common
|
|
234
290
|
formatting shortcuts, and keep toggle controls synchronized through `aria-pressed`.
|
|
291
|
+
`lumen-tabs` keeps the selected trigger visible in narrow horizontal lists and emits
|
|
292
|
+
`ui:tabs-change`; import `LumenTabsChangeDetail` or `LumenTabsChangeEvent` for its typed detail.
|
|
235
293
|
|
|
236
294
|
`<lumen-kanban-board>` and `<lumen-kanban-column value="…">` provide the same controlled board
|
|
237
295
|
contract. Mark ordinary card items with `data-ui-kanban-item` and put `data-ui-kanban-handle` on a
|
|
@@ -264,6 +322,13 @@ You can also use the shared document events: dispatch `ui:toast` to create, `ui:
|
|
|
264
322
|
update, and `ui:toast-dismiss` to dismiss runtime toasts. Toast actions emit `ui:toast-action`
|
|
265
323
|
unless an action supplies a custom event name.
|
|
266
324
|
|
|
325
|
+
Use `<lumen-error-state>` when a region or page cannot show its primary content. Keep its visible
|
|
326
|
+
heading, explanation, optional safe reference, and recovery actions in light DOM, label the region
|
|
327
|
+
with `aria-labelledby`, and use the documented `data-slot="error-state-*"` hooks. Lumen presents the
|
|
328
|
+
failure; application code owns exception capture, logging, and retry policy. See the repository
|
|
329
|
+
[Web Components error-handling guide](../../docs/error-handling.md#web-components) for the complete
|
|
330
|
+
light-DOM structure, ARIA ownership, retry boundary, and verification guidance.
|
|
331
|
+
|
|
267
332
|
## Motion
|
|
268
333
|
|
|
269
334
|
The elements adapter exposes the same motion vocabulary as Astro and React. Use
|
package/bin/lumen.mjs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type LumenCustomElementRegistry } from '../element-base.js';
|
|
2
|
+
export declare const lumenBadgeElementConfig: {
|
|
3
|
+
readonly attributeClasses: {
|
|
4
|
+
readonly variant: {
|
|
5
|
+
readonly default: "ui-badge--default";
|
|
6
|
+
readonly destructive: "ui-badge--destructive";
|
|
7
|
+
readonly outline: "ui-badge--outline";
|
|
8
|
+
readonly secondary: "ui-badge--secondary";
|
|
9
|
+
readonly success: "ui-badge--success";
|
|
10
|
+
readonly warning: "ui-badge--warning";
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
readonly baseClassName: "ui-badge";
|
|
14
|
+
readonly defaults: {
|
|
15
|
+
readonly variant: "default";
|
|
16
|
+
};
|
|
17
|
+
readonly tagName: "lumen-badge";
|
|
18
|
+
};
|
|
19
|
+
export declare const LumenBadgeElement: import("../element-base.js").LumenElementConstructor;
|
|
20
|
+
export declare const defineLumenBadge: (registry?: LumenCustomElementRegistry) => void;
|
|
21
|
+
//# sourceMappingURL=badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../src/components/badge.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAEhC,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;CAcG,CAAA;AAEvC,eAAO,MAAM,iBAAiB,sDAE7B,CAAA;AAED,eAAO,MAAM,gBAAgB,GAC3B,WAAW,0BAA0B,KACpC,IAEF,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createLumenElementClass, defineLumenElement } from '../element-base.js';
|
|
2
|
+
export const lumenBadgeElementConfig = {
|
|
3
|
+
attributeClasses: {
|
|
4
|
+
variant: {
|
|
5
|
+
default: 'ui-badge--default',
|
|
6
|
+
destructive: 'ui-badge--destructive',
|
|
7
|
+
outline: 'ui-badge--outline',
|
|
8
|
+
secondary: 'ui-badge--secondary',
|
|
9
|
+
success: 'ui-badge--success',
|
|
10
|
+
warning: 'ui-badge--warning'
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
baseClassName: 'ui-badge',
|
|
14
|
+
defaults: { variant: 'default' },
|
|
15
|
+
tagName: 'lumen-badge'
|
|
16
|
+
};
|
|
17
|
+
export const LumenBadgeElement = createLumenElementClass(lumenBadgeElementConfig);
|
|
18
|
+
export const defineLumenBadge = (registry) => {
|
|
19
|
+
defineLumenElement(lumenBadgeElementConfig, LumenBadgeElement, registry);
|
|
20
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type LumenCustomElementRegistry } from '../element-base.js';
|
|
2
|
+
export declare const lumenButtonElementConfig: {
|
|
3
|
+
readonly attributeClasses: {
|
|
4
|
+
readonly variant: {
|
|
5
|
+
readonly default: "ui-button--default";
|
|
6
|
+
readonly destructive: "ui-button--destructive";
|
|
7
|
+
readonly ghost: "ui-button--ghost";
|
|
8
|
+
readonly link: "ui-button--link";
|
|
9
|
+
readonly outline: "ui-button--outline";
|
|
10
|
+
readonly secondary: "ui-button--secondary";
|
|
11
|
+
};
|
|
12
|
+
readonly size: {
|
|
13
|
+
readonly default: "ui-button--default-size";
|
|
14
|
+
readonly icon: "ui-button--icon";
|
|
15
|
+
readonly lg: "ui-button--lg";
|
|
16
|
+
readonly sm: "ui-button--sm";
|
|
17
|
+
};
|
|
18
|
+
readonly disabled: {
|
|
19
|
+
readonly true: "ui-button--disabled";
|
|
20
|
+
};
|
|
21
|
+
readonly loading: {
|
|
22
|
+
readonly true: "ui-button--loading";
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
readonly baseClassName: "ui-button";
|
|
26
|
+
readonly defaults: {
|
|
27
|
+
readonly 'data-slot': "button";
|
|
28
|
+
readonly role: "button";
|
|
29
|
+
readonly size: "default";
|
|
30
|
+
readonly tabindex: "0";
|
|
31
|
+
readonly variant: "default";
|
|
32
|
+
};
|
|
33
|
+
readonly role: "button";
|
|
34
|
+
readonly tagName: "lumen-button";
|
|
35
|
+
};
|
|
36
|
+
export declare const LumenButtonElement: import("../element-base.js").LumenElementConstructor;
|
|
37
|
+
export declare const defineLumenButton: (registry?: LumenCustomElementRegistry) => void;
|
|
38
|
+
//# sourceMappingURL=button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/components/button.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAEhC,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6BE,CAAA;AAEvC,eAAO,MAAM,kBAAkB,sDAE9B,CAAA;AAED,eAAO,MAAM,iBAAiB,GAC5B,WAAW,0BAA0B,KACpC,IAEF,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createLumenElementClass, defineLumenElement } from '../element-base.js';
|
|
2
|
+
export const lumenButtonElementConfig = {
|
|
3
|
+
attributeClasses: {
|
|
4
|
+
variant: {
|
|
5
|
+
default: 'ui-button--default',
|
|
6
|
+
destructive: 'ui-button--destructive',
|
|
7
|
+
ghost: 'ui-button--ghost',
|
|
8
|
+
link: 'ui-button--link',
|
|
9
|
+
outline: 'ui-button--outline',
|
|
10
|
+
secondary: 'ui-button--secondary'
|
|
11
|
+
},
|
|
12
|
+
size: {
|
|
13
|
+
default: 'ui-button--default-size',
|
|
14
|
+
icon: 'ui-button--icon',
|
|
15
|
+
lg: 'ui-button--lg',
|
|
16
|
+
sm: 'ui-button--sm'
|
|
17
|
+
},
|
|
18
|
+
disabled: { true: 'ui-button--disabled' },
|
|
19
|
+
loading: { true: 'ui-button--loading' }
|
|
20
|
+
},
|
|
21
|
+
baseClassName: 'ui-button',
|
|
22
|
+
defaults: {
|
|
23
|
+
'data-slot': 'button',
|
|
24
|
+
role: 'button',
|
|
25
|
+
size: 'default',
|
|
26
|
+
tabindex: '0',
|
|
27
|
+
variant: 'default'
|
|
28
|
+
},
|
|
29
|
+
role: 'button',
|
|
30
|
+
tagName: 'lumen-button'
|
|
31
|
+
};
|
|
32
|
+
export const LumenButtonElement = createLumenElementClass(lumenButtonElementConfig);
|
|
33
|
+
export const defineLumenButton = (registry) => {
|
|
34
|
+
defineLumenElement(lumenButtonElementConfig, LumenButtonElement, registry);
|
|
35
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type LumenCustomElementRegistry } from '../element-base.js';
|
|
2
|
+
export declare const lumenCardElementConfig: {
|
|
3
|
+
readonly attributeClasses: {
|
|
4
|
+
readonly glass: {
|
|
5
|
+
readonly strong: "ui-card--glass ui-glass-strong";
|
|
6
|
+
readonly subtle: "ui-card--glass ui-glass-subtle";
|
|
7
|
+
readonly true: "ui-card--glass";
|
|
8
|
+
};
|
|
9
|
+
readonly variant: {
|
|
10
|
+
readonly glass: "ui-card--glass";
|
|
11
|
+
readonly interactive: "ui-card--interactive";
|
|
12
|
+
readonly muted: "ui-card--muted";
|
|
13
|
+
readonly unstyled: "ui-card--unstyled";
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
readonly baseClassName: "ui-card";
|
|
17
|
+
readonly defaults: {
|
|
18
|
+
readonly 'data-slot': "card";
|
|
19
|
+
readonly variant: "default";
|
|
20
|
+
};
|
|
21
|
+
readonly tagName: "lumen-card";
|
|
22
|
+
};
|
|
23
|
+
export declare const LumenCardElement: import("../element-base.js").LumenElementConstructor;
|
|
24
|
+
export declare const defineLumenCard: (registry?: LumenCustomElementRegistry) => void;
|
|
25
|
+
//# sourceMappingURL=card.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"card.d.ts","sourceRoot":"","sources":["../../src/components/card.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAEhC,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;CAiBI,CAAA;AAEvC,eAAO,MAAM,gBAAgB,sDAE5B,CAAA;AAED,eAAO,MAAM,eAAe,GAC1B,WAAW,0BAA0B,KACpC,IAEF,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createLumenElementClass, defineLumenElement } from '../element-base.js';
|
|
2
|
+
export const lumenCardElementConfig = {
|
|
3
|
+
attributeClasses: {
|
|
4
|
+
glass: {
|
|
5
|
+
strong: 'ui-card--glass ui-glass-strong',
|
|
6
|
+
subtle: 'ui-card--glass ui-glass-subtle',
|
|
7
|
+
true: 'ui-card--glass'
|
|
8
|
+
},
|
|
9
|
+
variant: {
|
|
10
|
+
glass: 'ui-card--glass',
|
|
11
|
+
interactive: 'ui-card--interactive',
|
|
12
|
+
muted: 'ui-card--muted',
|
|
13
|
+
unstyled: 'ui-card--unstyled'
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
baseClassName: 'ui-card',
|
|
17
|
+
defaults: { 'data-slot': 'card', variant: 'default' },
|
|
18
|
+
tagName: 'lumen-card'
|
|
19
|
+
};
|
|
20
|
+
export const LumenCardElement = createLumenElementClass(lumenCardElementConfig);
|
|
21
|
+
export const defineLumenCard = (registry) => {
|
|
22
|
+
defineLumenElement(lumenCardElementConfig, LumenCardElement, registry);
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type LumenCustomElementRegistry, LumenElement } from '../element-base.js';
|
|
2
|
+
export declare const lumenComboboxElementConfig: {
|
|
3
|
+
readonly baseClassName: "ui-combobox";
|
|
4
|
+
readonly defaults: {
|
|
5
|
+
readonly 'data-ui-combobox': "";
|
|
6
|
+
};
|
|
7
|
+
readonly tagName: "lumen-combobox";
|
|
8
|
+
};
|
|
9
|
+
export declare class LumenComboboxElement extends LumenElement {
|
|
10
|
+
static config: {
|
|
11
|
+
readonly baseClassName: "ui-combobox";
|
|
12
|
+
readonly defaults: {
|
|
13
|
+
readonly 'data-ui-combobox': "";
|
|
14
|
+
};
|
|
15
|
+
readonly tagName: "lumen-combobox";
|
|
16
|
+
};
|
|
17
|
+
private abortController;
|
|
18
|
+
connectedCallback(): void;
|
|
19
|
+
disconnectedCallback(): void;
|
|
20
|
+
private setupCombobox;
|
|
21
|
+
}
|
|
22
|
+
export declare const defineLumenCombobox: (registry?: LumenCustomElementRegistry) => void;
|
|
23
|
+
//# sourceMappingURL=combobox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combobox.d.ts","sourceRoot":"","sources":["../../src/components/combobox.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,YAAY,EAEb,MAAM,oBAAoB,CAAA;AAE3B,eAAO,MAAM,0BAA0B;;;;;;CAIA,CAAA;AAyBvC,qBAAa,oBAAqB,SAAQ,YAAY;IACpD,OAAgB,MAAM;;;;;;MAA6B;IAEnD,OAAO,CAAC,eAAe,CAA6B;IAE3C,iBAAiB;IAYjB,oBAAoB;IAM7B,OAAO,CAAC,aAAa;CAmJtB;AAED,eAAO,MAAM,mBAAmB,GAC9B,WAAW,0BAA0B,KACpC,IAIF,CAAA"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { defineLumenElement, LumenElement } from '../element-base.js';
|
|
2
|
+
export const lumenComboboxElementConfig = {
|
|
3
|
+
baseClassName: 'ui-combobox',
|
|
4
|
+
defaults: { 'data-ui-combobox': '' },
|
|
5
|
+
tagName: 'lumen-combobox'
|
|
6
|
+
};
|
|
7
|
+
let comboboxId = 0;
|
|
8
|
+
const createComboboxId = () => `ui-combobox-list-${++comboboxId}`;
|
|
9
|
+
const getEventTarget = (event) => {
|
|
10
|
+
const target = event.composedPath()[0] ?? event.target;
|
|
11
|
+
return target instanceof Node ? target : null;
|
|
12
|
+
};
|
|
13
|
+
const getLoopedIndex = (key, currentIndex, itemCount) => {
|
|
14
|
+
if (key === 'Home')
|
|
15
|
+
return 0;
|
|
16
|
+
if (key === 'End')
|
|
17
|
+
return itemCount - 1;
|
|
18
|
+
if (key === 'ArrowDown')
|
|
19
|
+
return (currentIndex + 1) % itemCount;
|
|
20
|
+
return (currentIndex - 1 + itemCount) % itemCount;
|
|
21
|
+
};
|
|
22
|
+
export class LumenComboboxElement extends LumenElement {
|
|
23
|
+
static config = lumenComboboxElementConfig;
|
|
24
|
+
abortController;
|
|
25
|
+
connectedCallback() {
|
|
26
|
+
super.connectedCallback();
|
|
27
|
+
if (typeof document === 'undefined')
|
|
28
|
+
return;
|
|
29
|
+
this.abortController?.abort();
|
|
30
|
+
this.abortController = new AbortController();
|
|
31
|
+
this.setupCombobox(this.abortController.signal);
|
|
32
|
+
}
|
|
33
|
+
disconnectedCallback() {
|
|
34
|
+
this.abortController?.abort();
|
|
35
|
+
this.abortController = undefined;
|
|
36
|
+
}
|
|
37
|
+
setupCombobox(signal) {
|
|
38
|
+
const input = this.querySelector('input[role="combobox"]');
|
|
39
|
+
const listbox = this.querySelector('[role="listbox"]');
|
|
40
|
+
if (!input || !listbox)
|
|
41
|
+
return;
|
|
42
|
+
const items = [...listbox.querySelectorAll('[role="option"]')];
|
|
43
|
+
if (!listbox.id)
|
|
44
|
+
listbox.id = createComboboxId();
|
|
45
|
+
input.setAttribute('aria-autocomplete', input.getAttribute('aria-autocomplete') ?? 'list');
|
|
46
|
+
input.setAttribute('aria-controls', listbox.id);
|
|
47
|
+
const getVisibleItems = () => items.filter(item => (!item.hidden && !item.hasAttribute('disabled') &&
|
|
48
|
+
item.getAttribute('aria-disabled') !== 'true'));
|
|
49
|
+
const close = () => {
|
|
50
|
+
input.setAttribute('aria-expanded', 'false');
|
|
51
|
+
listbox.hidden = true;
|
|
52
|
+
listbox.dataset.state = 'closed';
|
|
53
|
+
};
|
|
54
|
+
const open = () => {
|
|
55
|
+
input.setAttribute('aria-expanded', 'true');
|
|
56
|
+
listbox.hidden = false;
|
|
57
|
+
listbox.dataset.state = 'open';
|
|
58
|
+
};
|
|
59
|
+
const filter = () => {
|
|
60
|
+
const query = input.value.trim().toLowerCase();
|
|
61
|
+
for (const item of items) {
|
|
62
|
+
const value = item.getAttribute('data-value') ?? item.textContent.trim();
|
|
63
|
+
item.hidden = Boolean(query) && !value.toLowerCase().includes(query);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const select = (item) => {
|
|
67
|
+
input.value = item.getAttribute('data-value') ?? item.textContent.trim();
|
|
68
|
+
input.dispatchEvent(new Event('input', { bubbles: true }));
|
|
69
|
+
input.dispatchEvent(new Event('change', { bubbles: true }));
|
|
70
|
+
input.focus({ preventScroll: true });
|
|
71
|
+
close();
|
|
72
|
+
};
|
|
73
|
+
const focusItem = (item, key) => {
|
|
74
|
+
const visibleItems = getVisibleItems();
|
|
75
|
+
if (!visibleItems.length)
|
|
76
|
+
return;
|
|
77
|
+
const currentIndex = Math.max(0, visibleItems.indexOf(item));
|
|
78
|
+
visibleItems[getLoopedIndex(key, currentIndex, visibleItems.length)]?.focus();
|
|
79
|
+
};
|
|
80
|
+
close();
|
|
81
|
+
input.addEventListener('focus', open, { signal });
|
|
82
|
+
input.addEventListener('input', () => {
|
|
83
|
+
filter();
|
|
84
|
+
open();
|
|
85
|
+
}, { signal });
|
|
86
|
+
input.addEventListener('keydown', event => {
|
|
87
|
+
if (event.key === 'Escape') {
|
|
88
|
+
close();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (!['ArrowDown', 'ArrowUp', 'Enter'].includes(event.key))
|
|
92
|
+
return;
|
|
93
|
+
const visibleItems = getVisibleItems();
|
|
94
|
+
if (!visibleItems.length)
|
|
95
|
+
return;
|
|
96
|
+
event.preventDefault();
|
|
97
|
+
open();
|
|
98
|
+
if (event.key === 'Enter') {
|
|
99
|
+
const firstVisibleItem = visibleItems.at(0);
|
|
100
|
+
if (firstVisibleItem)
|
|
101
|
+
select(firstVisibleItem);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const targetIndex = event.key === 'ArrowUp' ? visibleItems.length - 1 : 0;
|
|
105
|
+
visibleItems[targetIndex]?.focus();
|
|
106
|
+
}, { signal });
|
|
107
|
+
for (const item of items) {
|
|
108
|
+
item.tabIndex = -1;
|
|
109
|
+
item.addEventListener('click', () => {
|
|
110
|
+
select(item);
|
|
111
|
+
}, { signal });
|
|
112
|
+
item.addEventListener('keydown', event => {
|
|
113
|
+
if (event.key === 'Escape') {
|
|
114
|
+
close();
|
|
115
|
+
input.focus({ preventScroll: true });
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
119
|
+
event.preventDefault();
|
|
120
|
+
select(item);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (!['ArrowDown', 'ArrowUp', 'Home', 'End'].includes(event.key))
|
|
124
|
+
return;
|
|
125
|
+
event.preventDefault();
|
|
126
|
+
focusItem(item, event.key);
|
|
127
|
+
}, { signal });
|
|
128
|
+
}
|
|
129
|
+
document.addEventListener('pointerdown', event => {
|
|
130
|
+
const target = getEventTarget(event);
|
|
131
|
+
if (target && !this.contains(target))
|
|
132
|
+
close();
|
|
133
|
+
}, { signal });
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
export const defineLumenCombobox = (registry) => {
|
|
137
|
+
defineLumenElement(lumenComboboxElementConfig, LumenComboboxElement, registry);
|
|
138
|
+
};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { type LumenCustomElementRegistry } from '../element-base.js';
|
|
2
|
+
export declare const lumenCardContentElementConfig: {
|
|
3
|
+
readonly baseClassName: "ui-card__content";
|
|
4
|
+
readonly defaults: {
|
|
5
|
+
readonly 'data-slot': "card-content";
|
|
6
|
+
};
|
|
7
|
+
readonly tagName: "lumen-card-content";
|
|
8
|
+
};
|
|
9
|
+
export declare const lumenCardDescriptionElementConfig: {
|
|
10
|
+
readonly baseClassName: "ui-card__description";
|
|
11
|
+
readonly defaults: {
|
|
12
|
+
readonly 'data-slot': "card-description";
|
|
13
|
+
};
|
|
14
|
+
readonly tagName: "lumen-card-description";
|
|
15
|
+
};
|
|
16
|
+
export declare const lumenCardFooterElementConfig: {
|
|
17
|
+
readonly baseClassName: "ui-card__footer";
|
|
18
|
+
readonly defaults: {
|
|
19
|
+
readonly 'data-slot': "card-footer";
|
|
20
|
+
};
|
|
21
|
+
readonly tagName: "lumen-card-footer";
|
|
22
|
+
};
|
|
23
|
+
export declare const lumenCardHeaderElementConfig: {
|
|
24
|
+
readonly baseClassName: "ui-card__header";
|
|
25
|
+
readonly defaults: {
|
|
26
|
+
readonly 'data-slot': "card-header";
|
|
27
|
+
};
|
|
28
|
+
readonly tagName: "lumen-card-header";
|
|
29
|
+
};
|
|
30
|
+
export declare const lumenCardTitleElementConfig: {
|
|
31
|
+
readonly baseClassName: "ui-card__title";
|
|
32
|
+
readonly defaults: {
|
|
33
|
+
readonly 'data-slot': "card-title";
|
|
34
|
+
};
|
|
35
|
+
readonly tagName: "lumen-card-title";
|
|
36
|
+
};
|
|
37
|
+
export declare const lumenContainerElementConfig: {
|
|
38
|
+
readonly attributeClasses: {
|
|
39
|
+
readonly size: {
|
|
40
|
+
readonly full: "ui-container--full";
|
|
41
|
+
readonly lg: "ui-container--lg";
|
|
42
|
+
readonly md: "ui-container--md";
|
|
43
|
+
readonly sm: "ui-container--sm";
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
readonly baseClassName: "ui-container";
|
|
47
|
+
readonly defaults: {
|
|
48
|
+
readonly 'data-ui-container': "";
|
|
49
|
+
readonly size: "lg";
|
|
50
|
+
};
|
|
51
|
+
readonly tagName: "lumen-container";
|
|
52
|
+
};
|
|
53
|
+
export declare const lumenDirectionElementConfig: {
|
|
54
|
+
readonly baseClassName: "ui-direction";
|
|
55
|
+
readonly defaults: {
|
|
56
|
+
readonly dir: "ltr";
|
|
57
|
+
};
|
|
58
|
+
readonly tagName: "lumen-direction";
|
|
59
|
+
};
|
|
60
|
+
export declare const lumenGridElementConfig: {
|
|
61
|
+
readonly attributeClasses: {
|
|
62
|
+
readonly columns: {
|
|
63
|
+
readonly 1: "ui-grid--columns-1";
|
|
64
|
+
readonly 2: "ui-grid--columns-2";
|
|
65
|
+
readonly 3: "ui-grid--columns-3";
|
|
66
|
+
readonly 4: "ui-grid--columns-4";
|
|
67
|
+
readonly 6: "ui-grid--columns-6";
|
|
68
|
+
readonly 12: "ui-grid--columns-12";
|
|
69
|
+
readonly auto: "ui-grid--columns-auto";
|
|
70
|
+
};
|
|
71
|
+
readonly gap: {
|
|
72
|
+
readonly lg: "ui-grid--gap-lg";
|
|
73
|
+
readonly md: "ui-grid--gap-md";
|
|
74
|
+
readonly none: "ui-grid--gap-none";
|
|
75
|
+
readonly sm: "ui-grid--gap-sm";
|
|
76
|
+
readonly xl: "ui-grid--gap-xl";
|
|
77
|
+
};
|
|
78
|
+
};
|
|
79
|
+
readonly baseClassName: "ui-grid";
|
|
80
|
+
readonly defaults: {
|
|
81
|
+
readonly 'data-ui-grid': "";
|
|
82
|
+
readonly columns: "auto";
|
|
83
|
+
readonly gap: "md";
|
|
84
|
+
};
|
|
85
|
+
readonly tagName: "lumen-grid";
|
|
86
|
+
};
|
|
87
|
+
export declare const lumenLabelElementConfig: {
|
|
88
|
+
readonly baseClassName: "ui-label";
|
|
89
|
+
readonly tagName: "lumen-label";
|
|
90
|
+
};
|
|
91
|
+
export declare const lumenSeparatorElementConfig: {
|
|
92
|
+
readonly attributeClasses: {
|
|
93
|
+
readonly orientation: {
|
|
94
|
+
readonly horizontal: "ui-separator--horizontal";
|
|
95
|
+
readonly vertical: "ui-separator--vertical";
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
readonly baseClassName: "ui-separator";
|
|
99
|
+
readonly defaults: {
|
|
100
|
+
readonly orientation: "horizontal";
|
|
101
|
+
};
|
|
102
|
+
readonly tagName: "lumen-separator";
|
|
103
|
+
};
|
|
104
|
+
export declare const lumenSkeletonElementConfig: {
|
|
105
|
+
readonly baseClassName: "ui-skeleton";
|
|
106
|
+
readonly tagName: "lumen-skeleton";
|
|
107
|
+
};
|
|
108
|
+
export declare const lumenSpinnerElementConfig: {
|
|
109
|
+
readonly baseClassName: "ui-spinner";
|
|
110
|
+
readonly tagName: "lumen-spinner";
|
|
111
|
+
};
|
|
112
|
+
export declare const lumenStackElementConfig: {
|
|
113
|
+
readonly attributeClasses: {
|
|
114
|
+
readonly direction: {
|
|
115
|
+
readonly horizontal: "ui-stack--horizontal";
|
|
116
|
+
readonly vertical: "ui-stack--vertical";
|
|
117
|
+
};
|
|
118
|
+
readonly gap: {
|
|
119
|
+
readonly lg: "ui-stack--gap-lg";
|
|
120
|
+
readonly md: "ui-stack--gap-md";
|
|
121
|
+
readonly none: "ui-stack--gap-none";
|
|
122
|
+
readonly sm: "ui-stack--gap-sm";
|
|
123
|
+
readonly xl: "ui-stack--gap-xl";
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
readonly baseClassName: "ui-stack";
|
|
127
|
+
readonly defaults: {
|
|
128
|
+
readonly 'data-ui-stack': "";
|
|
129
|
+
readonly direction: "vertical";
|
|
130
|
+
readonly gap: "md";
|
|
131
|
+
};
|
|
132
|
+
readonly tagName: "lumen-stack";
|
|
133
|
+
};
|
|
134
|
+
export declare const lumenTypographyElementConfig: {
|
|
135
|
+
readonly baseClassName: "ui-typography";
|
|
136
|
+
readonly tagName: "lumen-typography";
|
|
137
|
+
};
|
|
138
|
+
export declare const lumenVisuallyHiddenElementConfig: {
|
|
139
|
+
readonly baseClassName: "ui-visually-hidden";
|
|
140
|
+
readonly defaults: {
|
|
141
|
+
readonly 'data-ui-visually-hidden': "";
|
|
142
|
+
};
|
|
143
|
+
readonly tagName: "lumen-visually-hidden";
|
|
144
|
+
};
|
|
145
|
+
export declare const LumenCardContentElement: import("../element-base.js").LumenElementConstructor;
|
|
146
|
+
export declare const LumenCardDescriptionElement: import("../element-base.js").LumenElementConstructor;
|
|
147
|
+
export declare const LumenCardFooterElement: import("../element-base.js").LumenElementConstructor;
|
|
148
|
+
export declare const LumenCardHeaderElement: import("../element-base.js").LumenElementConstructor;
|
|
149
|
+
export declare const LumenCardTitleElement: import("../element-base.js").LumenElementConstructor;
|
|
150
|
+
export declare const LumenContainerElement: import("../element-base.js").LumenElementConstructor;
|
|
151
|
+
export declare const LumenDirectionElement: import("../element-base.js").LumenElementConstructor;
|
|
152
|
+
export declare const LumenGridElement: import("../element-base.js").LumenElementConstructor;
|
|
153
|
+
export declare const LumenLabelElement: import("../element-base.js").LumenElementConstructor;
|
|
154
|
+
export declare const LumenSeparatorElement: import("../element-base.js").LumenElementConstructor;
|
|
155
|
+
export declare const LumenSkeletonElement: import("../element-base.js").LumenElementConstructor;
|
|
156
|
+
export declare const LumenSpinnerElement: import("../element-base.js").LumenElementConstructor;
|
|
157
|
+
export declare const LumenStackElement: import("../element-base.js").LumenElementConstructor;
|
|
158
|
+
export declare const LumenTypographyElement: import("../element-base.js").LumenElementConstructor;
|
|
159
|
+
export declare const LumenVisuallyHiddenElement: import("../element-base.js").LumenElementConstructor;
|
|
160
|
+
export declare const defineLumenFoundations: (registry?: LumenCustomElementRegistry) => void;
|
|
161
|
+
//# sourceMappingURL=foundations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"foundations.d.ts","sourceRoot":"","sources":["../../src/components/foundations.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,0BAA0B,EAEhC,MAAM,oBAAoB,CAAA;AAO3B,eAAO,MAAM,6BAA6B;;;;;;CAIH,CAAA;AAEvC,eAAO,MAAM,iCAAiC;;;;;;CAIP,CAAA;AAEvC,eAAO,MAAM,4BAA4B;;;;;;CAIF,CAAA;AAEvC,eAAO,MAAM,4BAA4B;;;;;;CAIF,CAAA;AAEvC,eAAO,MAAM,2BAA2B;;;;;;CAID,CAAA;AAEvC,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;CAYD,CAAA;AAEvC,eAAO,MAAM,2BAA2B;;;;;;CAID,CAAA;AAEvC,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;CAsBI,CAAA;AAEvC,eAAO,MAAM,uBAAuB;;;CAGG,CAAA;AAEvC,eAAO,MAAM,2BAA2B;;;;;;;;;;;;CAUD,CAAA;AAEvC,eAAO,MAAM,0BAA0B;;;CAGA,CAAA;AAEvC,eAAO,MAAM,yBAAyB;;;CAGC,CAAA;AAEvC,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;;;CAiBG,CAAA;AAEvC,eAAO,MAAM,4BAA4B;;;CAGF,CAAA;AAEvC,eAAO,MAAM,gCAAgC;;;;;;CAIN,CAAA;AAkBvC,eAAO,MAAM,uBAAuB,sDAAsB,CAAA;AAC1D,eAAO,MAAM,2BAA2B,sDAA0B,CAAA;AAClE,eAAO,MAAM,sBAAsB,sDAAqB,CAAA;AACxD,eAAO,MAAM,sBAAsB,sDAAqB,CAAA;AACxD,eAAO,MAAM,qBAAqB,sDAAoB,CAAA;AACtD,eAAO,MAAM,qBAAqB,sDAAoB,CAAA;AACtD,eAAO,MAAM,qBAAqB,sDAAoB,CAAA;AACtD,eAAO,MAAM,gBAAgB,sDAAe,CAAA;AAC5C,eAAO,MAAM,iBAAiB,sDAAgB,CAAA;AAC9C,eAAO,MAAM,qBAAqB,sDAAoB,CAAA;AACtD,eAAO,MAAM,oBAAoB,sDAAmB,CAAA;AACpD,eAAO,MAAM,mBAAmB,sDAAkB,CAAA;AAClD,eAAO,MAAM,iBAAiB,sDAAgB,CAAA;AAC9C,eAAO,MAAM,sBAAsB,sDAAqB,CAAA;AACxD,eAAO,MAAM,0BAA0B,sDAAyB,CAAA;AAoBhE,eAAO,MAAM,sBAAsB,GACjC,WAAW,0BAA0B,KACpC,IAIF,CAAA"}
|