lapikit 0.7.0 → 0.7.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/@types/components.d.ts +7 -0
- package/dist/components/app/app.svelte +218 -272
- package/dist/directives.d.ts +14 -0
- package/dist/directives.js +128 -0
- package/dist/escaping.js +4 -1
- package/dist/html-mapped.js +5 -65
- package/dist/labs/sheet/sheet.svelte +60 -26
- package/dist/labs/sheet/sheet.svelte.d.ts +3 -0
- package/dist/utils/components.d.ts +35 -7
- package/dist/utils/components.js +174 -63
- package/dist/utils/directives.d.ts +20 -0
- package/dist/utils/directives.js +64 -0
- package/package.json +4 -2
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Svelte refuses the class: and style: directives on a component. On a <kit:...> tag, Lili turns them
|
|
3
|
+
* into the s-class_ / s-style_ props the components already handle:
|
|
4
|
+
* class:active -> s-class_active={active}
|
|
5
|
+
* class:gap={4} -> s-class_gap={4} (the component gives the class gap-4)
|
|
6
|
+
* style:opacity={0} -> s-style_opacity={0}
|
|
7
|
+
* style:color="red" -> s-style_color="red"
|
|
8
|
+
* A directive with a modifier (style:color|important) is left as it is: Svelte reports it.
|
|
9
|
+
*/
|
|
10
|
+
const identifier = /^[A-Za-z_$][\w$]*$/;
|
|
11
|
+
const nameEnd = /[\s=/>]/;
|
|
12
|
+
/** End index (exclusive) of the string starting at `start` (a quote or a backtick) */
|
|
13
|
+
function skipString(source, start) {
|
|
14
|
+
const quote = source[start];
|
|
15
|
+
let i = start + 1;
|
|
16
|
+
while (i < source.length) {
|
|
17
|
+
const ch = source[i];
|
|
18
|
+
if (ch === '\\') {
|
|
19
|
+
i += 2;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (ch === quote)
|
|
23
|
+
return i + 1;
|
|
24
|
+
// ${ ... } inside a template literal can hold braces and strings
|
|
25
|
+
if (quote === '`' && ch === '$' && source[i + 1] === '{') {
|
|
26
|
+
i = skipBraces(source, i + 1);
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
i++;
|
|
30
|
+
}
|
|
31
|
+
return source.length;
|
|
32
|
+
}
|
|
33
|
+
/** End index (exclusive) of the {...} expression starting at `start`, nested braces and strings included */
|
|
34
|
+
function skipBraces(source, start) {
|
|
35
|
+
let depth = 0;
|
|
36
|
+
let i = start;
|
|
37
|
+
while (i < source.length) {
|
|
38
|
+
const ch = source[i];
|
|
39
|
+
if (ch === '"' || ch === "'" || ch === '`') {
|
|
40
|
+
i = skipString(source, i);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (ch === '{')
|
|
44
|
+
depth++;
|
|
45
|
+
else if (ch === '}') {
|
|
46
|
+
depth--;
|
|
47
|
+
if (depth === 0)
|
|
48
|
+
return i + 1;
|
|
49
|
+
}
|
|
50
|
+
i++;
|
|
51
|
+
}
|
|
52
|
+
return source.length;
|
|
53
|
+
}
|
|
54
|
+
/** End index (exclusive) of an attribute value starting at `start` ({expr}, "text", 'text' or bare) */
|
|
55
|
+
function skipValue(source, start) {
|
|
56
|
+
const ch = source[start];
|
|
57
|
+
if (ch === '{')
|
|
58
|
+
return skipBraces(source, start);
|
|
59
|
+
if (ch === '"' || ch === "'")
|
|
60
|
+
return skipString(source, start);
|
|
61
|
+
let i = start;
|
|
62
|
+
while (i < source.length && !/[\s/>]/.test(source[i]))
|
|
63
|
+
i++;
|
|
64
|
+
return i;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Rewrites the class: and style: directives of the attributes of a tag (everything after its name).
|
|
68
|
+
* The values of the other attributes are skipped, so a "class:" inside a string or an expression is kept.
|
|
69
|
+
*/
|
|
70
|
+
export function rewriteDirectives(attributes) {
|
|
71
|
+
let output = '';
|
|
72
|
+
let i = 0;
|
|
73
|
+
while (i < attributes.length) {
|
|
74
|
+
const ch = attributes[i];
|
|
75
|
+
// A value (string or expression) of another attribute: copied as it is
|
|
76
|
+
if (ch === '"' || ch === "'") {
|
|
77
|
+
const end = skipString(attributes, i);
|
|
78
|
+
output += attributes.slice(i, end);
|
|
79
|
+
i = end;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (ch === '{') {
|
|
83
|
+
const end = skipBraces(attributes, i);
|
|
84
|
+
output += attributes.slice(i, end);
|
|
85
|
+
i = end;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
const startsAttribute = i === 0 || /\s/.test(attributes[i - 1]);
|
|
89
|
+
const kind = attributes.startsWith('class:', i)
|
|
90
|
+
? 'class'
|
|
91
|
+
: attributes.startsWith('style:', i)
|
|
92
|
+
? 'style'
|
|
93
|
+
: undefined;
|
|
94
|
+
if (!startsAttribute || !kind) {
|
|
95
|
+
output += ch;
|
|
96
|
+
i++;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
const nameStart = i + kind.length + 1;
|
|
100
|
+
let end = nameStart;
|
|
101
|
+
while (end < attributes.length && !nameEnd.test(attributes[end]))
|
|
102
|
+
end++;
|
|
103
|
+
const name = attributes.slice(nameStart, end);
|
|
104
|
+
// No name, or a modifier: left to Svelte
|
|
105
|
+
if (!name || name.includes('|')) {
|
|
106
|
+
output += ch;
|
|
107
|
+
i++;
|
|
108
|
+
continue;
|
|
109
|
+
}
|
|
110
|
+
const prop = `s-${kind}_${name}`;
|
|
111
|
+
if (attributes[end] === '=') {
|
|
112
|
+
const valueEnd = skipValue(attributes, end + 1);
|
|
113
|
+
output += `${prop}=${attributes.slice(end + 1, valueEnd)}`;
|
|
114
|
+
i = valueEnd;
|
|
115
|
+
}
|
|
116
|
+
else if (identifier.test(name)) {
|
|
117
|
+
// Shorthand: class:active uses the variable active
|
|
118
|
+
output += `${prop}={${name}}`;
|
|
119
|
+
i = end;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
// A shorthand needs a variable name (class:my-class has none): left to Svelte
|
|
123
|
+
output += attributes.slice(i, end);
|
|
124
|
+
i = end;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return output;
|
|
128
|
+
}
|
package/dist/escaping.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { rewriteDirectives } from './directives.js';
|
|
1
2
|
export const decodeSourceMap = (content, componentInfo) => {
|
|
2
3
|
const importedComponents = new Map();
|
|
3
4
|
const parts = [];
|
|
@@ -89,7 +90,9 @@ export const decodeSourceMap = (content, componentInfo) => {
|
|
|
89
90
|
}
|
|
90
91
|
if (isKnown) {
|
|
91
92
|
importedComponents.set(info.name, info.ref);
|
|
92
|
-
|
|
93
|
+
// class: / style: are refused by Svelte on a component: they become s-class_ / s-style_ props
|
|
94
|
+
parts.push(`<${info.name}${rewriteDirectives(content.slice(nameEnd, tagEnd + 1))}`);
|
|
95
|
+
changed = true;
|
|
93
96
|
changed = true;
|
|
94
97
|
}
|
|
95
98
|
else {
|
package/dist/html-mapped.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useClassName, useStyles } from './utils/components.js';
|
|
1
2
|
/**
|
|
2
3
|
* Computes a string of class names based on the provided sClass and classDirectiveProps.
|
|
3
4
|
* @param sClass - The s-class property which can be a string, array, or object.
|
|
@@ -5,48 +6,7 @@
|
|
|
5
6
|
* @returns A string of class names.
|
|
6
7
|
*/
|
|
7
8
|
export function computeSClasses(sClass, classDirectiveProps) {
|
|
8
|
-
|
|
9
|
-
// s-class string
|
|
10
|
-
if (typeof sClass === 'string' && sClass) {
|
|
11
|
-
classes.push(sClass);
|
|
12
|
-
}
|
|
13
|
-
// s-class array
|
|
14
|
-
if (Array.isArray(sClass)) {
|
|
15
|
-
for (const value of sClass) {
|
|
16
|
-
if (typeof value === 'string' && value) {
|
|
17
|
-
classes.push(value);
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
// s-class object
|
|
22
|
-
if (sClass && typeof sClass === 'object' && !Array.isArray(sClass)) {
|
|
23
|
-
const entries = Object.entries(sClass);
|
|
24
|
-
if (entries.length > 0) {
|
|
25
|
-
for (const [key, value] of entries) {
|
|
26
|
-
if (value === true) {
|
|
27
|
-
classes.push(key);
|
|
28
|
-
}
|
|
29
|
-
else if (typeof value === 'string' && value) {
|
|
30
|
-
classes.push(value);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
// s-class_xxx
|
|
36
|
-
const classEntries = Object.entries(classDirectiveProps);
|
|
37
|
-
if (classEntries.length > 0) {
|
|
38
|
-
for (const [key, value] of classEntries) {
|
|
39
|
-
// Use slice instead of replace for better performance (8 = 's-class_'.length)
|
|
40
|
-
const base = key.slice(8);
|
|
41
|
-
if (value === true) {
|
|
42
|
-
classes.push(base);
|
|
43
|
-
}
|
|
44
|
-
else if (typeof value === 'string' && value) {
|
|
45
|
-
classes.push(`${base}${value}`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
return classes.join(' ');
|
|
9
|
+
return useClassName({ sClass, classProps: classDirectiveProps });
|
|
50
10
|
}
|
|
51
11
|
/**
|
|
52
12
|
* Computes a string of style declarations based on the provided sStyle and styleDirectiveProps.
|
|
@@ -55,28 +15,7 @@ export function computeSClasses(sClass, classDirectiveProps) {
|
|
|
55
15
|
* @returns A string of style declarations.
|
|
56
16
|
*/
|
|
57
17
|
export function computeSStyles(sStyle, styleDirectiveProps) {
|
|
58
|
-
|
|
59
|
-
if (sStyle && typeof sStyle === 'object') {
|
|
60
|
-
const entries = Object.entries(sStyle);
|
|
61
|
-
if (entries.length > 0) {
|
|
62
|
-
for (const [key, value] of entries) {
|
|
63
|
-
if (value) {
|
|
64
|
-
styles.push(`${key}: ${value}`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
const styleEntries = Object.entries(styleDirectiveProps);
|
|
70
|
-
if (styleEntries.length > 0) {
|
|
71
|
-
for (const [key, value] of styleEntries) {
|
|
72
|
-
// Use slice instead of replace for better performance (8 = 's-style_'.length)
|
|
73
|
-
const base = key.slice(8);
|
|
74
|
-
if (value) {
|
|
75
|
-
styles.push(`${base}: ${value}`);
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return styles.join('; ');
|
|
18
|
+
return useStyles({ sStyle, styleProps: styleDirectiveProps });
|
|
80
19
|
}
|
|
81
20
|
/**
|
|
82
21
|
* Makes component props by separating s-class and s-style directives from other props.
|
|
@@ -95,7 +34,8 @@ export function makeComponentProps(props) {
|
|
|
95
34
|
else if (key.startsWith('s-style_')) {
|
|
96
35
|
styleProps[key] = value;
|
|
97
36
|
}
|
|
98
|
-
else if (
|
|
37
|
+
else if (key !== 's-class' && key !== 's-style') {
|
|
38
|
+
// Only the exact s-class / s-style are left out: a prop like s-classic is kept
|
|
99
39
|
restProps[key] = value;
|
|
100
40
|
}
|
|
101
41
|
}
|
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
* @description A simple sheet component for experimentation for developers Lapikit. Please don't use it in production.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import { makeComponentProps } from '../../html-mapped';
|
|
7
|
+
import { useComponentAttrs, useElevation } from '../../utils';
|
|
9
8
|
|
|
10
9
|
let {
|
|
11
10
|
class: className,
|
|
@@ -13,37 +12,72 @@
|
|
|
13
12
|
children,
|
|
14
13
|
's-class': sClass,
|
|
15
14
|
's-style': sStyle,
|
|
15
|
+
elevation,
|
|
16
|
+
rounded,
|
|
17
|
+
active,
|
|
16
18
|
...rest
|
|
17
19
|
} = $props();
|
|
18
20
|
|
|
19
|
-
let
|
|
20
|
-
|
|
21
|
+
let attrs = $derived(
|
|
22
|
+
useComponentAttrs('kit-sheet', { className, sClass, styleAttr, sStyle }, rest)
|
|
21
23
|
);
|
|
22
24
|
|
|
23
|
-
let
|
|
24
|
-
useClassName({
|
|
25
|
-
baseClass: 'kit-sheet',
|
|
26
|
-
className,
|
|
27
|
-
sClass,
|
|
28
|
-
classProps
|
|
29
|
-
})
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
let componentStyle = $derived(
|
|
33
|
-
useStyles({
|
|
34
|
-
styleAttr,
|
|
35
|
-
sStyle,
|
|
36
|
-
styleProps
|
|
37
|
-
})
|
|
38
|
-
);
|
|
25
|
+
let elevationState = $derived(useElevation(elevation));
|
|
39
26
|
</script>
|
|
40
27
|
|
|
41
|
-
<div
|
|
28
|
+
<div
|
|
29
|
+
class={attrs.class}
|
|
30
|
+
style={attrs.style}
|
|
31
|
+
data-rounded={rounded}
|
|
32
|
+
data-elevation={elevationState.base}
|
|
33
|
+
data-elevation-hover={elevationState.hover}
|
|
34
|
+
data-elevation-active={elevationState.active}
|
|
35
|
+
data-active={active}
|
|
36
|
+
{...attrs.rest}
|
|
37
|
+
>
|
|
42
38
|
{@render children()}
|
|
43
39
|
</div>
|
|
44
40
|
|
|
45
|
-
<style
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
41
|
+
<style>.kit-sheet {
|
|
42
|
+
display: flex;
|
|
43
|
+
background-color: var(--kit-color-surface-1);
|
|
44
|
+
color: var(--kit-color-text);
|
|
45
|
+
border-radius: var(--kit-sheet-radius);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.kit-sheet[data-active=true] {
|
|
49
|
+
background: var(--kit-color-accent);
|
|
50
|
+
color: var(--kit-on-accent);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* rounded
|
|
55
|
+
* @link https://lapikit.dev/docs/customize
|
|
56
|
+
*/
|
|
57
|
+
.kit-sheet[data-rounded=none] {
|
|
58
|
+
--kit-sheet-radius: var(--kit-shape-none);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.kit-sheet[data-rounded=xs] {
|
|
62
|
+
--kit-sheet-radius: var(--kit-shape-xs);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.kit-sheet[data-rounded=sm] {
|
|
66
|
+
--kit-sheet-radius: var(--kit-shape-sm);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.kit-sheet[data-rounded=md] {
|
|
70
|
+
--kit-sheet-radius: var(--kit-shape-md);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.kit-sheet[data-rounded=lg] {
|
|
74
|
+
--kit-sheet-radius: var(--kit-shape-lg);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.kit-sheet[data-rounded=xl] {
|
|
78
|
+
--kit-sheet-radius: var(--kit-shape-xl);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.kit-sheet[data-rounded=full] {
|
|
82
|
+
--kit-sheet-radius: var(--kit-shape-full);
|
|
83
|
+
}</style>
|
|
@@ -1,20 +1,30 @@
|
|
|
1
|
-
import type { ElevationProps, ElevationState, useClassNameProps, useStylesProps } from '../@types';
|
|
1
|
+
import type { ComponentAttrs, ElevationProps, ElevationState, PropValue, SStyleProp, useClassNameProps, useStylesProps } from '../@types';
|
|
2
|
+
import type { ClassValue } from 'svelte/elements';
|
|
3
|
+
/**
|
|
4
|
+
* The classes of the s-class_xxx directives (class:xxx on a kit tag):
|
|
5
|
+
* - true gives the name (class:active -> active);
|
|
6
|
+
* - a number or a text gives the name and the value, joined by a dash (class:gap={4} -> gap-4),
|
|
7
|
+
* without a dash when the name ends or the value starts with a separator (- _ : / .):
|
|
8
|
+
* s-class_gap-={4}, s-class_variant="-primary" and s-class_state=":active" keep working;
|
|
9
|
+
* - false, null, undefined and '' give nothing.
|
|
10
|
+
*/
|
|
11
|
+
export declare function directiveClasses(classProps: Record<string, PropValue> | undefined): string[];
|
|
2
12
|
/**
|
|
3
13
|
* useClassName - Utility to compute class names for a component.
|
|
4
14
|
* @param baseClass - The base class name for the component.
|
|
5
|
-
* @param className - Additional class names
|
|
15
|
+
* @param className - Additional class names: a string or an array of strings.
|
|
6
16
|
* @param sClass - The s-class property which can be a string, array, or object.
|
|
7
17
|
* @param classProps - An object containing s-class_xxx directives.
|
|
8
|
-
* @returns A computed class string.
|
|
18
|
+
* @returns A computed class string: no extra spaces, no duplicates, in the order of the inputs.
|
|
9
19
|
*/
|
|
10
20
|
export declare function useClassName({ baseClass, className, sClass, classProps }?: useClassNameProps): string;
|
|
11
21
|
export declare function useIsInteractive(props: Record<string, unknown>, tag: string, interactiveTags: readonly string[], interactive?: boolean): boolean;
|
|
12
22
|
/**
|
|
13
|
-
* useStyles - Utility to compute style declarations for a component (
|
|
14
|
-
* @param styleAttr - Inline style attribute as a string.
|
|
15
|
-
* @param sStyle - The s-style property
|
|
23
|
+
* useStyles - Utility to compute style declarations for a component (pure function).
|
|
24
|
+
* @param styleAttr - Inline style attribute as a string (raw CSS, kept as it is).
|
|
25
|
+
* @param sStyle - The s-style property: an object of property / value pairs (camelCase or kebab-case).
|
|
16
26
|
* @param styleProps - An object containing s-style_xxx directives.
|
|
17
|
-
* @returns A computed style string.
|
|
27
|
+
* @returns A computed style string; the style attribute comes last, so it wins.
|
|
18
28
|
*/
|
|
19
29
|
export declare function useStyles({ styleAttr, sStyle, styleProps }?: useStylesProps): string;
|
|
20
30
|
/**
|
|
@@ -24,3 +34,21 @@ export declare function useStyles({ styleAttr, sStyle, styleProps }?: useStylesP
|
|
|
24
34
|
* @returns An object with `base`, `hover` and `active` keys, `undefined` when not provided.
|
|
25
35
|
*/
|
|
26
36
|
export declare function useElevation(elevation?: ElevationProps | null): ElevationState;
|
|
37
|
+
/**
|
|
38
|
+
* useComponentAttrs - The class, style and other attributes of a labs component, in one call.
|
|
39
|
+
*
|
|
40
|
+
* The class is left to Svelte (clsx): class and s-class follow the same rules as class on an element,
|
|
41
|
+
* a string, an array, or an object whose keys are added when their value is truthy
|
|
42
|
+
* ({ active: isActive } -> active). The s-class_xxx directives (class:xxx on a kit tag) keep their
|
|
43
|
+
* rule: class:gap={4} -> gap-4.
|
|
44
|
+
*
|
|
45
|
+
* @param baseClass - The class of the component ('kit-btn-v2'), '' for none.
|
|
46
|
+
* @param props - The class, s-class, style and s-style props of the component.
|
|
47
|
+
* @param rest - The rest of the props: the s-class_xxx / s-style_xxx directives are taken out of it.
|
|
48
|
+
*/
|
|
49
|
+
export declare function useComponentAttrs(baseClass: string, { className, sClass, styleAttr, sStyle }: {
|
|
50
|
+
className?: ClassValue;
|
|
51
|
+
sClass?: ClassValue;
|
|
52
|
+
styleAttr?: string;
|
|
53
|
+
sStyle?: SStyleProp;
|
|
54
|
+
}, rest: Record<string, unknown>): ComponentAttrs;
|