lapikit 0.7.5 → 0.7.7
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/actions.d.ts +0 -2
- package/dist/@types/components.d.ts +2 -0
- package/dist/@types/props.d.ts +1 -1
- package/dist/components/accordion/accordion.types.d.ts +1 -4
- package/dist/components/accordion/modules/accordion-item.svelte +2 -2
- package/dist/components/index.d.ts +22 -4
- package/dist/components/modal/modal.d.ts +1 -5
- package/dist/components/modal/modal.js +2 -20
- package/dist/components/modal/modal.svelte +17 -23
- package/dist/components/modal/modal.types.d.ts +1 -1
- package/dist/components/tooltip/tooltip.svelte +27 -4
- package/dist/escaping.js +16 -34
- package/dist/framework.d.ts +2 -1
- package/dist/framework.js +10 -14
- package/dist/hooks/themes.svelte.d.ts +4 -5
- package/dist/hooks/themes.svelte.js +35 -30
- package/dist/labs/index.d.ts +1 -0
- package/package.json +7 -2
package/dist/@types/actions.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type MagicString from 'magic-string';
|
|
1
2
|
import type { Snippet } from 'svelte';
|
|
2
3
|
import type { ClassNameType, IdElementType, KitClassNameType, KitStylePropertiesType, PropValue, SStyleProp, StylePropertiesType } from './';
|
|
3
4
|
import type { ClassValue } from 'svelte/elements';
|
|
@@ -20,6 +21,7 @@ export interface Component extends Base {
|
|
|
20
21
|
export type KitComponentScan = {
|
|
21
22
|
code: string;
|
|
22
23
|
changed: boolean;
|
|
24
|
+
magic: MagicString;
|
|
23
25
|
importedComponents: Map<string, string>;
|
|
24
26
|
};
|
|
25
27
|
export type ComponentInfo = {
|
package/dist/@types/props.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export type PropValue = string | boolean | number | null | undefined;
|
|
2
2
|
export type SizeType = 'default' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
3
3
|
export type RoundedType = 0 | '0' | 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
4
|
-
export type DensityType = '
|
|
4
|
+
export type DensityType = 'dense' | 'compact' | 'default' | 'comfortable' | 'spacious';
|
|
5
5
|
export type ElevationType = '0' | '1' | '2' | '3' | '4' | '5';
|
|
6
6
|
export interface ElevationState {
|
|
7
7
|
base?: ElevationType;
|
|
@@ -16,9 +16,6 @@ export interface AccordionProps extends Component {
|
|
|
16
16
|
spacer?: boolean;
|
|
17
17
|
hideIcon?: boolean;
|
|
18
18
|
}
|
|
19
|
-
export type AccordionItemModelProps = {
|
|
20
|
-
open: boolean;
|
|
21
|
-
};
|
|
22
19
|
export interface AccordionItemProps extends Component {
|
|
23
20
|
ref?: HTMLElement | null;
|
|
24
21
|
is?: 'div';
|
|
@@ -29,7 +26,7 @@ export interface AccordionItemProps extends Component {
|
|
|
29
26
|
open?: boolean;
|
|
30
27
|
disabled?: boolean;
|
|
31
28
|
toggle?: (index: number | string) => void;
|
|
32
|
-
indicator?: Snippet<[
|
|
29
|
+
indicator?: Snippet<[ModelAccordionItemProps]>;
|
|
33
30
|
activator?: Snippet;
|
|
34
31
|
elevation?: ElevationProps;
|
|
35
32
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { useComponentAttrs, useElevation } from '../../../utils';
|
|
3
|
-
import type {
|
|
3
|
+
import type { AccordionItemProps, ModelAccordionItemProps } from '../accordion.types.js';
|
|
4
4
|
|
|
5
5
|
let {
|
|
6
6
|
ref = $bindable(),
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
const contentId = `${uid}-content`;
|
|
33
33
|
|
|
34
34
|
let safeOpen = $derived(!!open);
|
|
35
|
-
let model:
|
|
35
|
+
let model: ModelAccordionItemProps = {
|
|
36
36
|
get open() {
|
|
37
37
|
return safeOpen;
|
|
38
38
|
}
|
|
@@ -1,7 +1,25 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export type { ModelAccordionItemProps } from './accordion/accordion.types';
|
|
3
|
-
export type {
|
|
4
|
-
export type {
|
|
1
|
+
export type { ColorProps, ColorState, DensityType, ElevationProps, ElevationState, ElevationType, RoundedType, SizeType } from '../@types';
|
|
2
|
+
export type { AccordionProps, AccordionItemProps, ModelAccordionItemProps } from './accordion/accordion.types';
|
|
3
|
+
export type { AlertProps } from './alert/alert.types';
|
|
4
|
+
export type { AppProps } from './app/app.types';
|
|
5
|
+
export type { AppbarProps } from './appbar/appbar.types';
|
|
6
|
+
export type { AspectRatioProps, AspectRatioValue } from './aspect-ratio/aspect-ratio.types';
|
|
7
|
+
export type { AvatarProps } from './avatar/avatar.types';
|
|
8
|
+
export type { ButtonProps } from './btn/btn.types';
|
|
9
|
+
export type { CardProps, CardActionsProps, CardContainerProps, CardContentProps, CardMediaProps, CardTitleProps } from './card/card.types';
|
|
10
|
+
export type { ChipProps } from './chip/chip.types';
|
|
11
|
+
export type { DialogProps } from './dialog/dialog.types';
|
|
12
|
+
export type { DropdownProps, ModelDropdownProps, ModelDropdownHandleProps } from './dropdown/dropdown.types';
|
|
13
|
+
export type { FieldProps, FieldBaseProps, FieldControlProps, FieldVariant } from './field/field.types';
|
|
14
|
+
export type { IconProps } from './icon/icon.types';
|
|
15
|
+
export type { ListProps, ListItemProps, ListVariant, ListElement, ListItemElement } from './list/list.types';
|
|
16
|
+
export type { ModalProps } from './modal/modal.types';
|
|
17
|
+
export type { PopoverProps, ModelPopoverProps } from './popover/popover.types';
|
|
18
|
+
export type { SeparatorProps } from './separator/separator.types';
|
|
19
|
+
export type { SpacerProps } from './spacer/spacer.types';
|
|
20
|
+
export type { TextfieldProps } from './textfield/textfield.types';
|
|
21
|
+
export type { ToolbarProps } from './toolbar/toolbar.types';
|
|
22
|
+
export type { TooltipProps } from './tooltip/tooltip.types';
|
|
5
23
|
export { default as KitApp } from './app/app.svelte';
|
|
6
24
|
export { default as KitAppbar } from './appbar/appbar.svelte';
|
|
7
25
|
export { default as KitBtn } from './btn/btn.svelte';
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
import { type Writable } from 'svelte/store';
|
|
3
|
-
export declare const modalOpen: Writable<ModalState>;
|
|
4
|
-
export declare const modalStack: Writable<string[]>;
|
|
5
|
-
export declare function setOpenModal(state: boolean | 'persistent'): void;
|
|
1
|
+
export declare const modalStack: import("svelte/store").Writable<string[]>;
|
|
6
2
|
export declare const pushModal: (id: string) => void;
|
|
7
3
|
export declare const popModal: (id: string) => void;
|
|
@@ -1,26 +1,8 @@
|
|
|
1
|
-
import { lockScroll, unlockScroll } from '../../utils';
|
|
2
1
|
import { writable } from 'svelte/store';
|
|
3
|
-
// presets
|
|
4
|
-
const refModal = false;
|
|
5
|
-
// states
|
|
6
|
-
export const modalOpen = writable(refModal);
|
|
7
2
|
export const modalStack = writable([]);
|
|
8
|
-
export function setOpenModal(state) {
|
|
9
|
-
modalOpen.set(state);
|
|
10
|
-
}
|
|
11
3
|
export const pushModal = (id) => {
|
|
12
|
-
modalStack.update((stack) =>
|
|
13
|
-
if (stack.includes(id))
|
|
14
|
-
return stack;
|
|
15
|
-
lockScroll();
|
|
16
|
-
return [...stack, id];
|
|
17
|
-
});
|
|
4
|
+
modalStack.update((stack) => (stack.includes(id) ? stack : [...stack, id]));
|
|
18
5
|
};
|
|
19
6
|
export const popModal = (id) => {
|
|
20
|
-
modalStack.update((stack) =>
|
|
21
|
-
if (!stack.includes(id))
|
|
22
|
-
return stack;
|
|
23
|
-
unlockScroll();
|
|
24
|
-
return stack.filter((m) => m !== id);
|
|
25
|
-
});
|
|
7
|
+
modalStack.update((stack) => stack.filter((m) => m !== id));
|
|
26
8
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import { onDestroy } from 'svelte';
|
|
3
3
|
import { get } from 'svelte/store';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { useComponentAttrs, useElevation } from '../../utils';
|
|
5
|
+
import { modalStack, popModal, pushModal } from './modal.js';
|
|
6
6
|
import type { ModalProps } from './modal.types.js';
|
|
7
7
|
|
|
8
8
|
const modalId = $props.id();
|
|
@@ -44,7 +44,6 @@
|
|
|
44
44
|
)
|
|
45
45
|
);
|
|
46
46
|
let elevationState = $derived(useElevation(elevation));
|
|
47
|
-
let split = $derived(splitAriaAttrs(attrs.rest));
|
|
48
47
|
|
|
49
48
|
$effect(() => {
|
|
50
49
|
if (open && !wasPushed) {
|
|
@@ -56,18 +55,6 @@
|
|
|
56
55
|
}
|
|
57
56
|
});
|
|
58
57
|
|
|
59
|
-
$effect(() => {
|
|
60
|
-
if (open !== undefined && !contain) {
|
|
61
|
-
setOpenModal(open ? (persistent ? 'persistent' : true) : false);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
$effect(() => {
|
|
66
|
-
if ($modalOpen === false && !contain) {
|
|
67
|
-
open = false;
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
58
|
$effect(() => {
|
|
72
59
|
if (!open || !closeWithEsc || persistent) return;
|
|
73
60
|
|
|
@@ -94,16 +81,21 @@
|
|
|
94
81
|
function handleClose() {
|
|
95
82
|
if (!persistent) open = false;
|
|
96
83
|
}
|
|
84
|
+
|
|
85
|
+
function show(node: HTMLDialogElement) {
|
|
86
|
+
node.show();
|
|
87
|
+
return {
|
|
88
|
+
destroy() {
|
|
89
|
+
node.close();
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
97
93
|
</script>
|
|
98
94
|
|
|
99
95
|
{#if open}
|
|
100
96
|
<div
|
|
101
|
-
bind:this={ref}
|
|
102
97
|
class={attrs.class}
|
|
103
98
|
style={attrs.style}
|
|
104
|
-
role="dialog"
|
|
105
|
-
aria-modal={!contain}
|
|
106
|
-
{...split.aria}
|
|
107
99
|
data-contain={contain}
|
|
108
100
|
data-density={density}
|
|
109
101
|
data-rounded={rounded}
|
|
@@ -112,18 +104,19 @@
|
|
|
112
104
|
<div class="kit-modal__overlay" role="presentation" onclick={handleClose}></div>
|
|
113
105
|
{/if}
|
|
114
106
|
|
|
115
|
-
<
|
|
116
|
-
{
|
|
107
|
+
<dialog
|
|
108
|
+
bind:this={ref}
|
|
109
|
+
use:show
|
|
110
|
+
{...attrs.rest}
|
|
117
111
|
class={['kit-modal__content', classContent]}
|
|
118
112
|
data-size={size}
|
|
119
113
|
data-position={position}
|
|
120
114
|
data-elevation={elevationState.base}
|
|
121
115
|
data-elevation-hover={elevationState.hover}
|
|
122
116
|
data-elevation-active={elevationState.active}
|
|
123
|
-
onclick={(event: MouseEvent) => event.stopPropagation()}
|
|
124
117
|
>
|
|
125
118
|
{@render children?.()}
|
|
126
|
-
</
|
|
119
|
+
</dialog>
|
|
127
120
|
</div>
|
|
128
121
|
{/if}
|
|
129
122
|
|
|
@@ -188,6 +181,7 @@
|
|
|
188
181
|
}
|
|
189
182
|
.kit-modal__content {
|
|
190
183
|
position: fixed;
|
|
184
|
+
margin: 0;
|
|
191
185
|
top: var(--kit-modal-top);
|
|
192
186
|
right: var(--kit-modal-right);
|
|
193
187
|
bottom: var(--kit-modal-bottom);
|
|
@@ -3,7 +3,7 @@ import type { ColorProps, Component, ElevationProps, RoundedType } from '../../@
|
|
|
3
3
|
type ModalSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
|
|
4
4
|
type ModalPosition = 'top' | 'center' | 'bottom' | 'top-left' | 'top-right' | 'center-left' | 'center-right' | 'bottom-left' | 'bottom-right';
|
|
5
5
|
export interface ModalProps extends Component {
|
|
6
|
-
ref?:
|
|
6
|
+
ref?: HTMLDialogElement | null;
|
|
7
7
|
open?: boolean;
|
|
8
8
|
contain?: boolean;
|
|
9
9
|
size?: ModalSize;
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
|
|
34
34
|
let triggerRef = $state<HTMLElement | null>(null);
|
|
35
35
|
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
36
|
+
let focused = false;
|
|
36
37
|
let mounted = $derived(open || forceMount || !!tooltip);
|
|
37
38
|
|
|
38
39
|
const clearTimer = () => {
|
|
@@ -43,6 +44,7 @@
|
|
|
43
44
|
const handleHoverOpen = () => {
|
|
44
45
|
if (disabled) return;
|
|
45
46
|
clearTimer();
|
|
47
|
+
if (open) return;
|
|
46
48
|
timer = setTimeout(() => {
|
|
47
49
|
open = true;
|
|
48
50
|
timer = null;
|
|
@@ -51,6 +53,7 @@
|
|
|
51
53
|
|
|
52
54
|
const handleFocusOpen = () => {
|
|
53
55
|
if (disabled) return;
|
|
56
|
+
focused = true;
|
|
54
57
|
clearTimer();
|
|
55
58
|
open = true;
|
|
56
59
|
};
|
|
@@ -60,6 +63,17 @@
|
|
|
60
63
|
open = false;
|
|
61
64
|
};
|
|
62
65
|
|
|
66
|
+
const handleHoverClose = () => {
|
|
67
|
+
clearTimer();
|
|
68
|
+
if (focused) return;
|
|
69
|
+
timer = setTimeout(handleClose, 100);
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const handleFocusClose = () => {
|
|
73
|
+
focused = false;
|
|
74
|
+
handleClose();
|
|
75
|
+
};
|
|
76
|
+
|
|
63
77
|
$effect(() => {
|
|
64
78
|
if (disabled) open = false;
|
|
65
79
|
});
|
|
@@ -68,6 +82,15 @@
|
|
|
68
82
|
ref = triggerRef;
|
|
69
83
|
});
|
|
70
84
|
|
|
85
|
+
$effect(() => {
|
|
86
|
+
if (!open) return;
|
|
87
|
+
const onKeyDown = (event: KeyboardEvent) => {
|
|
88
|
+
if (event.key === 'Escape') handleClose();
|
|
89
|
+
};
|
|
90
|
+
document.addEventListener('keydown', onKeyDown);
|
|
91
|
+
return () => document.removeEventListener('keydown', onKeyDown);
|
|
92
|
+
});
|
|
93
|
+
|
|
71
94
|
onDestroy(clearTimer);
|
|
72
95
|
</script>
|
|
73
96
|
|
|
@@ -77,10 +100,9 @@
|
|
|
77
100
|
class="kit-tooltip-trigger"
|
|
78
101
|
aria-describedby={open ? tooltipId : undefined}
|
|
79
102
|
onmouseenter={handleHoverOpen}
|
|
80
|
-
onmouseleave={
|
|
103
|
+
onmouseleave={handleHoverClose}
|
|
81
104
|
onfocusin={handleFocusOpen}
|
|
82
|
-
onfocusout={
|
|
83
|
-
onkeydown={(event) => event.key === 'Escape' && handleClose()}
|
|
105
|
+
onfocusout={handleFocusClose}
|
|
84
106
|
>
|
|
85
107
|
{@render children?.()}
|
|
86
108
|
</span>
|
|
@@ -105,6 +127,8 @@
|
|
|
105
127
|
flip: avoidCollisions
|
|
106
128
|
}}
|
|
107
129
|
{...attrs.rest}
|
|
130
|
+
onmouseenter={clearTimer}
|
|
131
|
+
onmouseleave={handleHoverClose}
|
|
108
132
|
>
|
|
109
133
|
{#if tooltip}
|
|
110
134
|
{@render tooltip()}
|
|
@@ -171,7 +195,6 @@
|
|
|
171
195
|
color: var(--kit-tooltip-fg);
|
|
172
196
|
font-size: 0.875rem;
|
|
173
197
|
overflow-wrap: break-word;
|
|
174
|
-
pointer-events: none;
|
|
175
198
|
box-shadow: 0 16px 29px -10px color-mix(in oklab, var(--kit-color-shadow) 18%, transparent);
|
|
176
199
|
animation: kit-tooltip-enter 150ms ease;
|
|
177
200
|
}
|
package/dist/escaping.js
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
|
+
import MagicString from 'magic-string';
|
|
1
2
|
import { rewriteDirectives } from './directives.js';
|
|
2
3
|
export const decodeSourceMap = (content, componentInfo) => {
|
|
3
4
|
const importedComponents = new Map();
|
|
4
|
-
const
|
|
5
|
+
const magic = new MagicString(content);
|
|
5
6
|
let changed = false;
|
|
6
7
|
let index = 0;
|
|
7
8
|
const length = content.length;
|
|
8
9
|
while (index < length) {
|
|
9
10
|
const nextLt = content.indexOf('<', index);
|
|
10
|
-
if (nextLt === -1)
|
|
11
|
-
parts.push(content.slice(index));
|
|
11
|
+
if (nextLt === -1)
|
|
12
12
|
break;
|
|
13
|
-
}
|
|
14
|
-
if (nextLt > index) {
|
|
15
|
-
parts.push(content.slice(index, nextLt));
|
|
16
|
-
}
|
|
17
13
|
const ch = content[nextLt + 1];
|
|
18
14
|
const isClosing = ch === '/';
|
|
19
15
|
if (content.startsWith('<script', nextLt) || content.startsWith('<style', nextLt)) {
|
|
@@ -21,30 +17,22 @@ export const decodeSourceMap = (content, componentInfo) => {
|
|
|
21
17
|
const nameEnd = nextLt + tagName.length + 1;
|
|
22
18
|
const afterName = content[nameEnd];
|
|
23
19
|
if (afterName && !/[\s>/]/.test(afterName)) {
|
|
24
|
-
parts.push('<');
|
|
25
20
|
index = nextLt + 1;
|
|
26
21
|
continue;
|
|
27
22
|
}
|
|
28
23
|
const openEnd = findTagEnd(content, nameEnd);
|
|
29
|
-
if (openEnd === -1)
|
|
30
|
-
parts.push(content.slice(nextLt));
|
|
24
|
+
if (openEnd === -1)
|
|
31
25
|
break;
|
|
32
|
-
}
|
|
33
26
|
const closeTag = `</${tagName}>`;
|
|
34
27
|
const closeStart = content.indexOf(closeTag, openEnd + 1);
|
|
35
|
-
if (closeStart === -1)
|
|
36
|
-
parts.push(content.slice(nextLt));
|
|
28
|
+
if (closeStart === -1)
|
|
37
29
|
break;
|
|
38
|
-
|
|
39
|
-
const closeEnd = closeStart + closeTag.length;
|
|
40
|
-
parts.push(content.slice(nextLt, closeEnd));
|
|
41
|
-
index = closeEnd;
|
|
30
|
+
index = closeStart + closeTag.length;
|
|
42
31
|
continue;
|
|
43
32
|
}
|
|
44
33
|
const isKitTag = (!isClosing && content.startsWith('<kit:', nextLt)) ||
|
|
45
34
|
(isClosing && content.startsWith('</kit:', nextLt));
|
|
46
35
|
if (!isKitTag) {
|
|
47
|
-
parts.push('<');
|
|
48
36
|
index = nextLt + 1;
|
|
49
37
|
continue;
|
|
50
38
|
}
|
|
@@ -60,7 +48,6 @@ export const decodeSourceMap = (content, componentInfo) => {
|
|
|
60
48
|
}
|
|
61
49
|
const shortName = content.slice(nameStart, nameEnd);
|
|
62
50
|
if (!shortName) {
|
|
63
|
-
parts.push('<');
|
|
64
51
|
index = nextLt + 1;
|
|
65
52
|
continue;
|
|
66
53
|
}
|
|
@@ -68,40 +55,35 @@ export const decodeSourceMap = (content, componentInfo) => {
|
|
|
68
55
|
const isKnown = info !== undefined;
|
|
69
56
|
if (isClosing) {
|
|
70
57
|
const tagEnd = content.indexOf('>', nameEnd);
|
|
71
|
-
if (tagEnd === -1)
|
|
72
|
-
parts.push(content.slice(nextLt));
|
|
58
|
+
if (tagEnd === -1)
|
|
73
59
|
break;
|
|
74
|
-
}
|
|
75
60
|
if (isKnown) {
|
|
76
61
|
importedComponents.set(info.name, info.ref);
|
|
77
|
-
|
|
62
|
+
magic.overwrite(nextLt, tagEnd + 1, `</${info.name}>`);
|
|
78
63
|
changed = true;
|
|
79
64
|
}
|
|
80
|
-
else {
|
|
81
|
-
parts.push(content.slice(nextLt, tagEnd + 1));
|
|
82
|
-
}
|
|
83
65
|
index = tagEnd + 1;
|
|
84
66
|
continue;
|
|
85
67
|
}
|
|
86
68
|
const tagEnd = findTagEnd(content, nameEnd);
|
|
87
|
-
if (tagEnd === -1)
|
|
88
|
-
parts.push(content.slice(nextLt));
|
|
69
|
+
if (tagEnd === -1)
|
|
89
70
|
break;
|
|
90
|
-
}
|
|
91
71
|
if (isKnown) {
|
|
92
72
|
importedComponents.set(info.name, info.ref);
|
|
73
|
+
magic.overwrite(nextLt, nameEnd, `<${info.name}`);
|
|
93
74
|
// class: / style: are refused by Svelte on a component: they become s-class_ / s-style_ props
|
|
94
|
-
|
|
75
|
+
const attributes = content.slice(nameEnd, tagEnd + 1);
|
|
76
|
+
const rewritten = rewriteDirectives(attributes);
|
|
77
|
+
if (rewritten !== attributes)
|
|
78
|
+
magic.overwrite(nameEnd, tagEnd + 1, rewritten);
|
|
95
79
|
changed = true;
|
|
96
80
|
}
|
|
97
|
-
else {
|
|
98
|
-
parts.push(content.slice(nextLt, tagEnd + 1));
|
|
99
|
-
}
|
|
100
81
|
index = tagEnd + 1;
|
|
101
82
|
}
|
|
102
83
|
return {
|
|
103
|
-
code: changed ?
|
|
84
|
+
code: changed ? magic.toString() : content,
|
|
104
85
|
changed,
|
|
86
|
+
magic,
|
|
105
87
|
importedComponents
|
|
106
88
|
};
|
|
107
89
|
};
|
package/dist/framework.d.ts
CHANGED
|
@@ -2,10 +2,11 @@ import type { LapikitPreprocessOptions } from './@types/index.js';
|
|
|
2
2
|
export declare function componentName(shortName: string): string;
|
|
3
3
|
export declare function collectDeclaredIdentifiers(content: string): Set<string>;
|
|
4
4
|
export declare function liliCore(options?: LapikitPreprocessOptions): {
|
|
5
|
-
markup({ content }: {
|
|
5
|
+
markup({ content, filename }: {
|
|
6
6
|
content: string;
|
|
7
7
|
filename?: string;
|
|
8
8
|
}): {
|
|
9
9
|
code: string;
|
|
10
|
+
map: import("magic-string").SourceMap;
|
|
10
11
|
} | undefined;
|
|
11
12
|
};
|
package/dist/framework.js
CHANGED
|
@@ -40,7 +40,7 @@ export function collectDeclaredIdentifiers(content) {
|
|
|
40
40
|
}
|
|
41
41
|
export function liliCore(options) {
|
|
42
42
|
return {
|
|
43
|
-
markup({ content }) {
|
|
43
|
+
markup({ content, filename }) {
|
|
44
44
|
if (!content.includes('<kit:'))
|
|
45
45
|
return;
|
|
46
46
|
const componentInfo = new Map();
|
|
@@ -72,7 +72,7 @@ export function liliCore(options) {
|
|
|
72
72
|
const scanResult = decodeSourceMap(content, componentInfo);
|
|
73
73
|
if (!scanResult.changed)
|
|
74
74
|
return;
|
|
75
|
-
|
|
75
|
+
const { magic } = scanResult;
|
|
76
76
|
const importedComponents = scanResult.importedComponents;
|
|
77
77
|
// components already declared by the user (manual import, alias...) are not imported again
|
|
78
78
|
const declared = collectDeclaredIdentifiers(content);
|
|
@@ -103,28 +103,24 @@ export function liliCore(options) {
|
|
|
103
103
|
})
|
|
104
104
|
.join('');
|
|
105
105
|
const scriptRegex = /<script(?![^>]*\bmodule\b)([^>]*)>/;
|
|
106
|
-
const scriptMatch =
|
|
106
|
+
const scriptMatch = content.match(scriptRegex);
|
|
107
107
|
if (scriptMatch && scriptMatch.index !== undefined) {
|
|
108
|
-
|
|
109
|
-
processedContent =
|
|
110
|
-
processedContent.slice(0, insertPos) + importLines + processedContent.slice(insertPos);
|
|
108
|
+
magic.appendLeft(scriptMatch.index + scriptMatch[0].length, importLines);
|
|
111
109
|
}
|
|
112
110
|
else {
|
|
113
|
-
const moduleScriptMatch =
|
|
111
|
+
const moduleScriptMatch = content.match(/<script[^>]*\bmodule\b[^>]*>/);
|
|
114
112
|
if (moduleScriptMatch && moduleScriptMatch.index !== undefined) {
|
|
115
|
-
const moduleScriptEnd =
|
|
116
|
-
|
|
117
|
-
processedContent.slice(0, moduleScriptEnd) +
|
|
118
|
-
`\n\n<script>${importLines}\n</script>` +
|
|
119
|
-
processedContent.slice(moduleScriptEnd);
|
|
113
|
+
const moduleScriptEnd = content.indexOf('</script>', moduleScriptMatch.index) + '</script>'.length;
|
|
114
|
+
magic.appendLeft(moduleScriptEnd, `\n\n<script>${importLines}\n</script>`);
|
|
120
115
|
}
|
|
121
116
|
else {
|
|
122
|
-
|
|
117
|
+
magic.prepend(`<script>${importLines}\n</script>\n\n`);
|
|
123
118
|
}
|
|
124
119
|
}
|
|
125
120
|
}
|
|
126
121
|
return {
|
|
127
|
-
code:
|
|
122
|
+
code: magic.toString(),
|
|
123
|
+
map: magic.generateMap({ hires: true, source: filename, includeContent: true })
|
|
128
124
|
};
|
|
129
125
|
}
|
|
130
126
|
};
|
|
@@ -4,9 +4,8 @@ export declare function createGlobalTheme(params?: ThemeOptions): {
|
|
|
4
4
|
readonly active: string;
|
|
5
5
|
};
|
|
6
6
|
export declare function createTheme(): ThemeAction;
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
/**
|
|
8
|
+
* themeScript - An inline script that applies the stored theme before the page is painted (no flash with SSR).
|
|
9
|
+
* Put it in the <head>: {@html themeScript()} inside <svelte:head>.
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
export declare const theme: Writable<string>;
|
|
11
|
+
export declare function themeScript(params?: Pick<ThemeOptions, 'name' | 'key'>): string;
|
|
@@ -3,6 +3,27 @@ const isBrowser = typeof window !== 'undefined';
|
|
|
3
3
|
// presets
|
|
4
4
|
const default_theme = 'light';
|
|
5
5
|
const default_storage_key = '@lapikit/theme';
|
|
6
|
+
// localStorage can throw (private browsing, blocked storage): the theme still applies, without being kept
|
|
7
|
+
function readStorage(key) {
|
|
8
|
+
if (!isBrowser)
|
|
9
|
+
return null;
|
|
10
|
+
try {
|
|
11
|
+
return localStorage.getItem(key);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function writeStorage(key, name) {
|
|
18
|
+
if (!isBrowser)
|
|
19
|
+
return;
|
|
20
|
+
try {
|
|
21
|
+
localStorage.setItem(key, name);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// ignored: see readStorage
|
|
25
|
+
}
|
|
26
|
+
}
|
|
6
27
|
function generateGlobalTheme() {
|
|
7
28
|
let active = $state(default_theme);
|
|
8
29
|
let key = default_storage_key;
|
|
@@ -15,16 +36,14 @@ function generateGlobalTheme() {
|
|
|
15
36
|
}
|
|
16
37
|
function set(name) {
|
|
17
38
|
applyToHtml(name);
|
|
18
|
-
|
|
19
|
-
localStorage.setItem(key, name);
|
|
20
|
-
}
|
|
39
|
+
writeStorage(key, name);
|
|
21
40
|
}
|
|
22
41
|
function init(params = {}) {
|
|
23
42
|
if (initialized)
|
|
24
43
|
return;
|
|
25
44
|
initialized = true;
|
|
26
45
|
key = params.key ?? default_storage_key;
|
|
27
|
-
const stored =
|
|
46
|
+
const stored = readStorage(key);
|
|
28
47
|
applyToHtml(stored ?? params.name ?? default_theme);
|
|
29
48
|
}
|
|
30
49
|
return {
|
|
@@ -59,9 +78,8 @@ export function createTheme() {
|
|
|
59
78
|
}
|
|
60
79
|
function set(name) {
|
|
61
80
|
applyTheme(name);
|
|
62
|
-
if (
|
|
63
|
-
|
|
64
|
-
}
|
|
81
|
+
if (key)
|
|
82
|
+
writeStorage(key, name);
|
|
65
83
|
}
|
|
66
84
|
// skip the effect's first automatic pass so the mount's own initial value (from
|
|
67
85
|
// `name`, storage or default) isn't immediately clobbered by the current global value
|
|
@@ -80,7 +98,7 @@ export function createTheme() {
|
|
|
80
98
|
node = n;
|
|
81
99
|
key = params.key;
|
|
82
100
|
overridden = params.overridden ?? false;
|
|
83
|
-
const stored =
|
|
101
|
+
const stored = key ? readStorage(key) : null;
|
|
84
102
|
applyTheme(stored ?? params.name ?? (overridden ? default_theme : refGlobalTheme.active));
|
|
85
103
|
return {
|
|
86
104
|
update(newParams = {}) {
|
|
@@ -100,26 +118,13 @@ export function createTheme() {
|
|
|
100
118
|
}
|
|
101
119
|
};
|
|
102
120
|
}
|
|
103
|
-
/**
|
|
104
|
-
*
|
|
105
|
-
*
|
|
121
|
+
/**
|
|
122
|
+
* themeScript - An inline script that applies the stored theme before the page is painted (no flash with SSR).
|
|
123
|
+
* Put it in the <head>: {@html themeScript()} inside <svelte:head>.
|
|
106
124
|
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
// if (isBrowser) {
|
|
114
|
-
// const html = document.documentElement;
|
|
115
|
-
// html.classList.forEach((cls) => {
|
|
116
|
-
// if (cls.startsWith('kit-theme--')) {
|
|
117
|
-
// html.classList.remove(cls);
|
|
118
|
-
// }
|
|
119
|
-
// });
|
|
120
|
-
// html.classList.add(`kit-theme--${name}`);
|
|
121
|
-
// localStorage.setItem(key, name);
|
|
122
|
-
// }
|
|
123
|
-
// return name;
|
|
124
|
-
// });
|
|
125
|
-
// }
|
|
125
|
+
export function themeScript(params = {}) {
|
|
126
|
+
const key = JSON.stringify(params.key ?? default_storage_key);
|
|
127
|
+
const name = JSON.stringify(params.name ?? null);
|
|
128
|
+
const code = `(function(){var t=null;try{t=localStorage.getItem(${key})}catch(e){}t=t||${name};if(t)document.documentElement.setAttribute('data-kit-theme',t)})()`;
|
|
129
|
+
return `<script>${code.replace(/</g, '\\u003c')}</script>`;
|
|
130
|
+
}
|
package/dist/labs/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lapikit",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -77,11 +77,16 @@
|
|
|
77
77
|
"default": "./dist/labs/*"
|
|
78
78
|
},
|
|
79
79
|
"./actions": {
|
|
80
|
+
"types": "./dist/hooks/actions.d.ts",
|
|
80
81
|
"default": "./dist/hooks/actions.js"
|
|
81
82
|
}
|
|
82
83
|
},
|
|
84
|
+
"engines": {
|
|
85
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
86
|
+
},
|
|
83
87
|
"dependencies": {
|
|
84
|
-
"esm-env": "^1.2.2"
|
|
88
|
+
"esm-env": "^1.2.2",
|
|
89
|
+
"magic-string": "^0.30.21"
|
|
85
90
|
},
|
|
86
91
|
"peerDependencies": {
|
|
87
92
|
"svelte": "^5.20.0"
|