luxen-ui 0.19.0 → 0.19.1
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/dist/metadata/index.json +1 -1
- package/package.json +1 -1
- package/vite-plugin.ts +44 -14
package/dist/metadata/index.json
CHANGED
package/package.json
CHANGED
package/vite-plugin.ts
CHANGED
|
@@ -6,29 +6,45 @@ import postcssPrefix from './postcss-plugin-prefix.js';
|
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Map of element base name → class name as exported by `luxen-ui/<name>/element`.
|
|
9
|
-
* Keep in sync with `src/html/registry.ts` `ElementBaseName`.
|
|
10
9
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
10
|
+
* Every custom element the library defines must appear here: an element absent
|
|
11
|
+
* from this map emits no typing at all (`emitTypes` consumers get an untyped
|
|
12
|
+
* `Element`), and an entry naming a class that isn't exported at
|
|
13
|
+
* `<name>/element` emits an import with no file behind it. Neither is
|
|
14
|
+
* observable at runtime, so `scripts/check-metadata.mjs` (check 6) validates
|
|
15
|
+
* both directions against `dist/custom-elements.json` on every build — that is
|
|
16
|
+
* why this map is exported. The same check ties each element back to
|
|
17
|
+
* `ElementBaseName` in `src/html/registry.ts`, so all three stay in step.
|
|
18
|
+
*
|
|
19
|
+
* `toast-item` is deliberately absent: it is registered from `toast/index.ts`
|
|
20
|
+
* and has no `dist/elements/toast-item/` module to import a type from.
|
|
15
21
|
*/
|
|
16
|
-
const ELEMENT_CLASSES: Record<string, string> = {
|
|
22
|
+
export const ELEMENT_CLASSES: Record<string, string> = {
|
|
17
23
|
alert: 'Alert',
|
|
24
|
+
'alert-dialog': 'AlertDialog',
|
|
18
25
|
avatar: 'Avatar',
|
|
19
26
|
badge: 'Badge',
|
|
27
|
+
'button-group': 'ButtonGroup',
|
|
20
28
|
carousel: 'Carousel',
|
|
21
29
|
'carousel-item': 'CarouselItem',
|
|
30
|
+
'color-scheme-icon': 'ColorSchemeIcon',
|
|
31
|
+
combobox: 'Combobox',
|
|
22
32
|
dialog: 'Dialog',
|
|
23
33
|
divider: 'Divider',
|
|
24
34
|
drawer: 'Drawer',
|
|
25
35
|
dropdown: 'Dropdown',
|
|
26
36
|
'dropdown-item': 'DropdownItem',
|
|
37
|
+
'dropdown-label': 'DropdownLabel',
|
|
38
|
+
'form-field': 'FormField',
|
|
27
39
|
icon: 'Icon',
|
|
40
|
+
'input-group': 'InputGroup',
|
|
28
41
|
'input-otp': 'InputOtp',
|
|
29
42
|
'input-stepper': 'InputStepper',
|
|
30
43
|
popover: 'Popover',
|
|
44
|
+
'prose-editor': 'ProseEditor',
|
|
31
45
|
rating: 'Rating',
|
|
46
|
+
'segmented-control': 'SegmentedControl',
|
|
47
|
+
select: 'Select',
|
|
32
48
|
skeleton: 'Skeleton',
|
|
33
49
|
slider: 'Slider',
|
|
34
50
|
spinner: 'Spinner',
|
|
@@ -37,8 +53,8 @@ const ELEMENT_CLASSES: Record<string, string> = {
|
|
|
37
53
|
'stories-viewer': 'LuxenStoriesViewer',
|
|
38
54
|
story: 'LuxenStory',
|
|
39
55
|
tabs: 'Tabs',
|
|
56
|
+
tag: 'Tag',
|
|
40
57
|
toast: 'Toast',
|
|
41
|
-
'toast-item': 'ToastItem',
|
|
42
58
|
tooltip: 'Tooltip',
|
|
43
59
|
tree: 'Tree',
|
|
44
60
|
'tree-item': 'TreeItem',
|
|
@@ -241,12 +257,19 @@ async function loadLuxenConfig(): Promise<Partial<LuxenOptions> | null> {
|
|
|
241
257
|
function syncTypesFile(prefix: string, cfg: EmitTypesOptions): void {
|
|
242
258
|
const target = resolve(process.cwd(), cfg.path);
|
|
243
259
|
const names = cfg.elements ?? Object.keys(ELEMENT_CLASSES);
|
|
244
|
-
|
|
260
|
+
// Own-property lookup, not `in`: a hand-written `elements` subset is consumer
|
|
261
|
+
// input, and `'toString' in ELEMENT_CLASSES` is true — the prototype chain
|
|
262
|
+
// would smuggle `Object`'s own members into the emitted file. (`Object.hasOwn`
|
|
263
|
+
// would read better but is ES2022; this file compiles against `lib: ES2020`.)
|
|
264
|
+
const isElement = (n: string): boolean =>
|
|
265
|
+
Object.prototype.hasOwnProperty.call(ELEMENT_CLASSES, n);
|
|
266
|
+
|
|
267
|
+
const unknown = names.filter((n) => !isElement(n));
|
|
245
268
|
if (unknown.length > 0) {
|
|
246
269
|
console.warn(`[luxen] emitTypes: unknown element(s) ignored — ${unknown.join(', ')}`);
|
|
247
270
|
}
|
|
248
271
|
|
|
249
|
-
const known = names.filter(
|
|
272
|
+
const known = names.filter(isElement);
|
|
250
273
|
const pkg = cfg.packageName || 'luxen-ui';
|
|
251
274
|
const content =
|
|
252
275
|
cfg.target === 'vue'
|
|
@@ -323,16 +346,23 @@ import type { DefineComponent } from 'vue';
|
|
|
323
346
|
import type { LuxenElement } from '${pkg}/luxen-element';
|
|
324
347
|
${imports}
|
|
325
348
|
|
|
326
|
-
// Keep only each element's OWN data props
|
|
327
|
-
// LuxenElement / Lit / HTMLElement
|
|
328
|
-
//
|
|
329
|
-
//
|
|
349
|
+
// Keep only each element's OWN settable data props: subtract everything
|
|
350
|
+
// inherited from LuxenElement / Lit / HTMLElement, drop methods, and drop
|
|
351
|
+
// read-only members — get-only accessors (\`validity\`, \`willValidate\`) and
|
|
352
|
+
// \`readonly\` fields (\`_internals\`) are element state a template cannot set,
|
|
353
|
+
// and several elements inherit a stack of them from the form-associated base.
|
|
354
|
+
// Any \`on*\` listener stays allowed. Autocomplete lands on the real props while
|
|
355
|
+
// unknown attributes and bad values still error.
|
|
356
|
+
type Writable<T, K extends keyof T> = (<G>() => G extends { [P in K]: T[K] } ? 1 : 2) extends
|
|
357
|
+
<G>() => G extends { -readonly [P in K]: T[K] } ? 1 : 2
|
|
358
|
+
? K
|
|
359
|
+
: never;
|
|
330
360
|
type OwnKeys<T> = {
|
|
331
361
|
[K in keyof T]-?: K extends keyof LuxenElement
|
|
332
362
|
? never
|
|
333
363
|
: T[K] extends (...args: never[]) => unknown
|
|
334
364
|
? never
|
|
335
|
-
: K
|
|
365
|
+
: Writable<T, K>;
|
|
336
366
|
}[keyof T];
|
|
337
367
|
type ElementProps<T> = Partial<Pick<T, OwnKeys<T>>> &
|
|
338
368
|
Record<\`on\${string}\`, ((event: Event) => void) | undefined>;
|