grundlage 0.0.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/README +170 -0
- package/dist/grundlage.d.ts +192 -0
- package/dist/grundlage.js +602 -0
- package/dist/grundlage.umd.cjs +1 -0
- package/package.json +25 -0
package/README
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# Grundlage - a web component base rendering function
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The Template System provides a declarative way to handle dynamic content, conditional rendering, lists, and asynchronous operations using native HTML `<template>` elements. It uses slots for state management while maintaining compatibility with regular Web Component slots.
|
|
6
|
+
|
|
7
|
+
## Core Concepts
|
|
8
|
+
|
|
9
|
+
### Template Boundaries
|
|
10
|
+
|
|
11
|
+
Each template creates its own boundary for state management and error handling. Content and errors are scoped to their immediate parent template, creating clean separation between different template blocks.
|
|
12
|
+
|
|
13
|
+
### State Management Slots
|
|
14
|
+
|
|
15
|
+
Templates use slots to manage different states (content, fallback, error, etc.). The default slot is used for the primary content, while other states are handled through named slots.
|
|
16
|
+
|
|
17
|
+
## Basic Usage
|
|
18
|
+
|
|
19
|
+
### Conditional Rendering
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<template when="${condition}">
|
|
23
|
+
<!-- Default slot (content) -->
|
|
24
|
+
<div>Main content shown when condition is true</div>
|
|
25
|
+
|
|
26
|
+
<!-- Fallback state -->
|
|
27
|
+
<template slot="fallback">
|
|
28
|
+
<div>Shown when condition is false</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<!-- Error state -->
|
|
32
|
+
<template slot="error">
|
|
33
|
+
<div>${error => error.message}</div>
|
|
34
|
+
</template>
|
|
35
|
+
</template>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Async Operations
|
|
39
|
+
|
|
40
|
+
```html
|
|
41
|
+
<template suspense="${fetchData}">
|
|
42
|
+
<!-- Default slot for success state -->
|
|
43
|
+
<div>${data => data.result}</div>
|
|
44
|
+
|
|
45
|
+
<!-- Loading state -->
|
|
46
|
+
<template slot="fallback" when="${() => status() === 'loading'}">
|
|
47
|
+
<div>Loading...</div>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<!-- Error state -->
|
|
51
|
+
<template slot="error">
|
|
52
|
+
<div>${error => error.message}</div>
|
|
53
|
+
</template>
|
|
54
|
+
</template>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### List Rendering
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<template each="${items}">
|
|
61
|
+
<!-- Item template -->
|
|
62
|
+
<template slot="item" key="${item => item.id}">
|
|
63
|
+
<div>${item => item.name}</div>
|
|
64
|
+
</template>
|
|
65
|
+
|
|
66
|
+
<!-- Empty state -->
|
|
67
|
+
<template slot="empty">
|
|
68
|
+
<div>No items available</div>
|
|
69
|
+
</template>
|
|
70
|
+
</template>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Slot Rules
|
|
74
|
+
|
|
75
|
+
1. The default (unnamed) slot is used for primary content
|
|
76
|
+
2. Special state slots:
|
|
77
|
+
|
|
78
|
+
- `fallback`: Alternative content
|
|
79
|
+
- `error`: Error handling
|
|
80
|
+
- `empty`: Empty state for lists
|
|
81
|
+
- `item`: List item template
|
|
82
|
+
|
|
83
|
+
3. Multiple elements can use the same slot:
|
|
84
|
+
|
|
85
|
+
```html
|
|
86
|
+
<template when="${condition}">
|
|
87
|
+
<!-- Both fallbacks exist, visibility controlled by conditions -->
|
|
88
|
+
<template slot="fallback" when="${loading}">
|
|
89
|
+
<div>Loading...</div>
|
|
90
|
+
</template>
|
|
91
|
+
<template slot="fallback" when="${timeout}">
|
|
92
|
+
<div>Timeout...</div>
|
|
93
|
+
</template>
|
|
94
|
+
</template>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Template Boundaries and Nesting
|
|
98
|
+
|
|
99
|
+
### Scope Rules
|
|
100
|
+
|
|
101
|
+
1. Everything can be slotted, only templates have render functionality
|
|
102
|
+
2. Templates create strict boundaries
|
|
103
|
+
3. Slots belong to their immediate parent template
|
|
104
|
+
4. Errors are caught by the nearest parent template
|
|
105
|
+
|
|
106
|
+
```html
|
|
107
|
+
<template when="${outerCondition}">
|
|
108
|
+
<div>Outer content</div>
|
|
109
|
+
|
|
110
|
+
<!-- This template is self-contained -->
|
|
111
|
+
<template when="${innerCondition}">
|
|
112
|
+
<div>Inner content</div>
|
|
113
|
+
<!-- This fallback belongs to inner template -->
|
|
114
|
+
<template slot="fallback">
|
|
115
|
+
<div>Inner fallback</div>
|
|
116
|
+
</template>
|
|
117
|
+
</template>
|
|
118
|
+
|
|
119
|
+
<!-- This fallback belongs to outer template -->
|
|
120
|
+
<template slot="fallback">
|
|
121
|
+
<div>Outer fallback</div>
|
|
122
|
+
</template>
|
|
123
|
+
</template>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Component Integration
|
|
127
|
+
|
|
128
|
+
Templates inside component slots are self-contained:
|
|
129
|
+
|
|
130
|
+
```html
|
|
131
|
+
<my-component>
|
|
132
|
+
<!-- This template manages its own states -->
|
|
133
|
+
<template when="${condition}" slot="footer">
|
|
134
|
+
<div>Footer content</div>
|
|
135
|
+
<!-- Fallback belongs to when template, not component -->
|
|
136
|
+
<template slot="fallback">
|
|
137
|
+
<div>Footer fallback</div>
|
|
138
|
+
</template>
|
|
139
|
+
</template>
|
|
140
|
+
</my-component>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Special Considerations
|
|
144
|
+
|
|
145
|
+
1. State management attributes (`when`, `each`, `suspense`) can only be used on `<template>` elements
|
|
146
|
+
|
|
147
|
+
2. Dynamic slot names are not supported
|
|
148
|
+
|
|
149
|
+
3. Template order doesn't affect slot rendering, but content within slots is rendered in document order
|
|
150
|
+
|
|
151
|
+
## Error Handling
|
|
152
|
+
|
|
153
|
+
Errors are caught by the nearest parent template with an error slot:
|
|
154
|
+
|
|
155
|
+
```html
|
|
156
|
+
<template when="${condition}">
|
|
157
|
+
<template suspense="${fetchData}">
|
|
158
|
+
<div>${data => data.result}</div>
|
|
159
|
+
<!-- Fetch errors are caught here -->
|
|
160
|
+
<template slot="error">
|
|
161
|
+
<div>Fetch error: ${error => error.message}</div>
|
|
162
|
+
</template>
|
|
163
|
+
</template>
|
|
164
|
+
|
|
165
|
+
<!-- Other errors in the when template are caught here -->
|
|
166
|
+
<template slot="error">
|
|
167
|
+
<div>General error: ${error => error.message}</div>
|
|
168
|
+
</template>
|
|
169
|
+
</template>
|
|
170
|
+
```
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
declare module "mount/helper" {
|
|
2
|
+
export const isIterable: (value: unknown) => value is Array<unknown> | Set<unknown> | Map<unknown, unknown>;
|
|
3
|
+
export const remove: (start: Node, end: Node) => DocumentFragment;
|
|
4
|
+
}
|
|
5
|
+
declare module "mount/mount-list" {
|
|
6
|
+
import type { Context } from "context/index";
|
|
7
|
+
import { type TemplateBus } from "mount/mount";
|
|
8
|
+
export const mountList: (template: HTMLTemplateElement, templateBus: TemplateBus, context: Context) => void;
|
|
9
|
+
}
|
|
10
|
+
declare module "mount/update-content" {
|
|
11
|
+
import type { Context } from "context/index";
|
|
12
|
+
import { type TemplateBus } from "mount/mount";
|
|
13
|
+
export const updateContent: (stubbedElement: Element, templateBus: TemplateBus, context: Context) => void;
|
|
14
|
+
}
|
|
15
|
+
declare module "mount/update-style" {
|
|
16
|
+
import type { Context } from "context/index";
|
|
17
|
+
export const updateStyle: (styleElement: HTMLStyleElement, context: Context) => void;
|
|
18
|
+
}
|
|
19
|
+
declare module "mount/update-attributes" {
|
|
20
|
+
import type { Context } from "context/index";
|
|
21
|
+
import type { TemplateBus } from "mount/mount";
|
|
22
|
+
export const updateAttributes: (stubbedElement: HTMLElement, templateBus: TemplateBus, context: Context) => void;
|
|
23
|
+
}
|
|
24
|
+
declare module "mount/update-dom" {
|
|
25
|
+
import type { Context } from "context/index";
|
|
26
|
+
import { type TemplateBus } from "mount/mount";
|
|
27
|
+
export const updateDOM: (content: DocumentFragment, templateBus: TemplateBus, context: Context) => DocumentFragment;
|
|
28
|
+
}
|
|
29
|
+
declare module "mount/mount" {
|
|
30
|
+
import type { Context } from "context/index";
|
|
31
|
+
import { type InternalAsyncSignal, type SignalGetter, type ValueOf } from "context/signal";
|
|
32
|
+
export const defaultWhen: () => boolean;
|
|
33
|
+
export const noop: () => undefined;
|
|
34
|
+
export const defaultKeyFn: (element: unknown, index?: number, array?: Array<unknown>) => string;
|
|
35
|
+
export type MountData = {
|
|
36
|
+
keyFn: (element: unknown, index?: number, array?: Array<unknown>) => string;
|
|
37
|
+
when: (activeValue?: unknown) => unknown;
|
|
38
|
+
each: (activeValue?: unknown) => Array<unknown>;
|
|
39
|
+
suspense: ((activeValue?: unknown) => unknown) & InternalAsyncSignal;
|
|
40
|
+
ref: (rangeOrElement: Range | Element) => void;
|
|
41
|
+
};
|
|
42
|
+
export type TemplateSlots = {
|
|
43
|
+
content: DocumentFragment;
|
|
44
|
+
fallbacks: DocumentFragment;
|
|
45
|
+
errors: DocumentFragment;
|
|
46
|
+
empty: DocumentFragment;
|
|
47
|
+
loading: DocumentFragment;
|
|
48
|
+
};
|
|
49
|
+
const RENDER_CASE: {
|
|
50
|
+
readonly CONTENT: 0;
|
|
51
|
+
readonly FALLBACK: 1;
|
|
52
|
+
readonly EMPTY: 2;
|
|
53
|
+
readonly LOADING: 3;
|
|
54
|
+
readonly ERROR: 4;
|
|
55
|
+
};
|
|
56
|
+
export const extractTemplateSlots: (originalTemplate: HTMLTemplateElement) => Record<ValueOf<typeof RENDER_CASE>, DocumentFragment>;
|
|
57
|
+
export const extractTemplateFunctionality: (template: HTMLTemplateElement, { keyFn }: TemplateBus, { values }: Context) => MountData;
|
|
58
|
+
export type MountPoint = [Comment, Comment];
|
|
59
|
+
export const createMountPoint: (template: Element, name?: string) => MountPoint;
|
|
60
|
+
export type TemplateBus = {
|
|
61
|
+
activeValue: SignalGetter<unknown>;
|
|
62
|
+
keyFn: (element: unknown, index?: number, array?: Array<unknown>) => string;
|
|
63
|
+
};
|
|
64
|
+
export const shouldRerender: (slots: Record<ValueOf<typeof RENDER_CASE>, DocumentFragment>, data: MountData, { activeValue }: TemplateBus, context: Context) => {
|
|
65
|
+
status: SignalGetter<0 | 1 | 2 | 3 | 4>;
|
|
66
|
+
result: SignalGetter<undefined>;
|
|
67
|
+
staticResult: () => any;
|
|
68
|
+
};
|
|
69
|
+
export type ComponentLifecylce = {
|
|
70
|
+
beforeRender: (activeValue: unknown) => void;
|
|
71
|
+
afterRender: (activeValue: unknown) => void;
|
|
72
|
+
};
|
|
73
|
+
export const extractTemplateCallbacks: (templateElement: HTMLTemplateElement, context: Context) => ComponentLifecylce;
|
|
74
|
+
export const mount: (templateElement: HTMLTemplateElement, templateBus: TemplateBus, context: Context) => void;
|
|
75
|
+
}
|
|
76
|
+
declare module "context/signal" {
|
|
77
|
+
export const ASYNC_STATES: {
|
|
78
|
+
readonly IDLE: -1;
|
|
79
|
+
readonly ERROR: 0;
|
|
80
|
+
readonly LOADING: 1;
|
|
81
|
+
readonly SUCCESS: 2;
|
|
82
|
+
};
|
|
83
|
+
export type ValueOf<T> = T[keyof T];
|
|
84
|
+
export interface Effect {
|
|
85
|
+
execute: VoidFunction;
|
|
86
|
+
dependencies: Set<Set<Effect>>;
|
|
87
|
+
parent: Effect;
|
|
88
|
+
children: Set<Effect>;
|
|
89
|
+
cleanupEffects: Set<VoidFunction>;
|
|
90
|
+
dirty: boolean;
|
|
91
|
+
}
|
|
92
|
+
export type InternalAsyncSignal = {
|
|
93
|
+
error: SignalGetter<Error>;
|
|
94
|
+
status: SignalGetter<ValueOf<typeof ASYNC_STATES>>;
|
|
95
|
+
refetch: VoidFunction;
|
|
96
|
+
};
|
|
97
|
+
export type AsyncSignalGetter<Value> = SignalGetter<Value> & InternalAsyncSignal;
|
|
98
|
+
type AsyncSignal<Value> = [AsyncSignalGetter<Value>, SignalSetter<Value>];
|
|
99
|
+
export type SignalSetter<Value> = (newValue: Value | ((prevValue: Value) => Value)) => void;
|
|
100
|
+
export type SignalGetter<Value> = () => Value;
|
|
101
|
+
export type Signal<Value> = [SignalGetter<Value>, SignalSetter<Value>];
|
|
102
|
+
export type CreateSignalFn = <Value>(initialValue: Value) => Signal<Value>;
|
|
103
|
+
type ComputedFn = <Value>(fn: (isToplevel: boolean) => Value) => SignalGetter<Value>;
|
|
104
|
+
type CreateAsyncFn = <Value>(createPromise: () => Promise<Value>, trigger?: SignalGetter<unknown>) => AsyncSignal<Value>;
|
|
105
|
+
type RefFn = () => (...args: [] | [Node] | [Node, Node]) => Array<Node> | Node | undefined;
|
|
106
|
+
type FromSignalFn = <Value>(externalSignal: Signal<Value>) => Signal<Value>;
|
|
107
|
+
export type Reactivity = {
|
|
108
|
+
create: CreateSignalFn;
|
|
109
|
+
createAsync: CreateAsyncFn;
|
|
110
|
+
computed: ComputedFn;
|
|
111
|
+
ref: RefFn;
|
|
112
|
+
dispose: VoidFunction;
|
|
113
|
+
fromSignal: FromSignalFn;
|
|
114
|
+
context: Effect[];
|
|
115
|
+
onCleanup: (callback: VoidFunction) => void;
|
|
116
|
+
};
|
|
117
|
+
export const cleanup: (effect: Effect) => void;
|
|
118
|
+
export const createSignalReactivity: () => Reactivity;
|
|
119
|
+
}
|
|
120
|
+
declare module "context/slots" {
|
|
121
|
+
import type { Reactivity } from "context/signal";
|
|
122
|
+
export const getSlotContent: (root: Element | ShadowRoot, signal: Reactivity) => (name?: string) => (() => Node[]) | undefined;
|
|
123
|
+
}
|
|
124
|
+
declare module "context/index" {
|
|
125
|
+
import { type Reactivity, type SignalGetter } from "context/signal";
|
|
126
|
+
export type Context = {
|
|
127
|
+
signal: Reactivity;
|
|
128
|
+
mountCallbacks: Set<VoidFunction>;
|
|
129
|
+
unMountCallbacks: Set<VoidFunction>;
|
|
130
|
+
dispose: VoidFunction;
|
|
131
|
+
values: Map<string, unknown>;
|
|
132
|
+
};
|
|
133
|
+
export type UserContext = Pick<Context, "signal"> & {
|
|
134
|
+
lifecyle: {
|
|
135
|
+
onMount: (callback: VoidFunction) => void;
|
|
136
|
+
onUnmount: (callback: VoidFunction) => void;
|
|
137
|
+
};
|
|
138
|
+
elements: {
|
|
139
|
+
shadowRoot: () => ShadowRoot;
|
|
140
|
+
slots: (name?: string) => SignalGetter<Node[]>;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
export const createUserContext: (shadowRoot: ShadowRoot, { mountCallbacks, unMountCallbacks, signal }: Context) => UserContext;
|
|
144
|
+
export const createContext: () => Context;
|
|
145
|
+
}
|
|
146
|
+
declare module "template/html" {
|
|
147
|
+
import { renderKey } from "template/helper";
|
|
148
|
+
export type ParsingResult = {
|
|
149
|
+
template: string;
|
|
150
|
+
values: Map<string, unknown>;
|
|
151
|
+
name: string;
|
|
152
|
+
key: typeof renderKey;
|
|
153
|
+
};
|
|
154
|
+
export const html: (tokens: TemplateStringsArray, ...dynamicValues: Array<unknown>) => ParsingResult;
|
|
155
|
+
}
|
|
156
|
+
declare module "template/helper" {
|
|
157
|
+
import type { CssParsingResult } from "template/css";
|
|
158
|
+
import type { ParsingResult } from "template/html";
|
|
159
|
+
export const renderKey: unique symbol;
|
|
160
|
+
export const isInsideOfTag: (template: string) => boolean;
|
|
161
|
+
export const isStatic: (value: unknown) => boolean;
|
|
162
|
+
export const isNestedRender: (nextValue: unknown) => nextValue is ParsingResult;
|
|
163
|
+
export const createStub: () => string;
|
|
164
|
+
export const mergeMaps: (from: Map<unknown, unknown>, to: Map<unknown, unknown>) => Map<unknown, unknown>;
|
|
165
|
+
export const cssKey: unique symbol;
|
|
166
|
+
export const createStyleStub: () => string;
|
|
167
|
+
export const isUsedAsClassIdentifier: (node: CssParsingResult) => boolean;
|
|
168
|
+
export const isNestedStyleRender: (nextValue: unknown) => nextValue is CssParsingResult;
|
|
169
|
+
}
|
|
170
|
+
declare module "template/css" {
|
|
171
|
+
import { cssKey } from "template/helper";
|
|
172
|
+
export type CssParsingResult = {
|
|
173
|
+
template: string;
|
|
174
|
+
values: Map<string, unknown>;
|
|
175
|
+
key: typeof cssKey;
|
|
176
|
+
name: string;
|
|
177
|
+
};
|
|
178
|
+
export const css: (tokens: TemplateStringsArray, ...dynamicValues: Array<unknown>) => CssParsingResult;
|
|
179
|
+
}
|
|
180
|
+
declare module "index" {
|
|
181
|
+
import { type UserContext } from "context/index";
|
|
182
|
+
import { type CssParsingResult } from "template/css";
|
|
183
|
+
import { type ParsingResult } from "template/html";
|
|
184
|
+
export type ComponentOptions = {};
|
|
185
|
+
export type Props = Record<string, unknown>;
|
|
186
|
+
export type RenderFn = (props: Props, context: UserContext) => ParsingResult;
|
|
187
|
+
export type ComponentProps<Props = Record<string, unknown>> = ((name: string, renderFn: RenderFn, options?: ComponentOptions) => (props?: Props) => ParsingResult) & {
|
|
188
|
+
html: (tokens: TemplateStringsArray, ...dynamicValues: Array<unknown>) => ParsingResult;
|
|
189
|
+
css: (tokens: TemplateStringsArray, ...dynamicValues: Array<unknown>) => CssParsingResult;
|
|
190
|
+
};
|
|
191
|
+
export const render: ComponentProps;
|
|
192
|
+
}
|
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
const st = (t) => !!t?.[Symbol.iterator], A = (t, e) => {
|
|
2
|
+
const n = new DocumentFragment();
|
|
3
|
+
let r = t.nextSibling;
|
|
4
|
+
for (; r && r !== e; ) {
|
|
5
|
+
const s = r.nextSibling;
|
|
6
|
+
n.append(r), r = s;
|
|
7
|
+
}
|
|
8
|
+
return n;
|
|
9
|
+
}, b = {
|
|
10
|
+
ADD: 0,
|
|
11
|
+
DELETE: 1,
|
|
12
|
+
MOVE: 2
|
|
13
|
+
}, ot = (t, e = I, n) => {
|
|
14
|
+
const r = [], s = t.map(e), o = new Set(s), a = Math.max(
|
|
15
|
+
s.length,
|
|
16
|
+
n.positions.length
|
|
17
|
+
);
|
|
18
|
+
let c = 0, i = 0;
|
|
19
|
+
for (let u = 0; u < a; u++) {
|
|
20
|
+
const d = s[c], l = n.positions[i];
|
|
21
|
+
if (d === l) {
|
|
22
|
+
c += 1, i += 1;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (!d) {
|
|
26
|
+
r.push({
|
|
27
|
+
type: b.DELETE,
|
|
28
|
+
key: l,
|
|
29
|
+
relatedKey: "",
|
|
30
|
+
callback: S
|
|
31
|
+
}), i += 1;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (!n.keys.has(d)) {
|
|
35
|
+
const p = t[c];
|
|
36
|
+
r.push({
|
|
37
|
+
type: b.ADD,
|
|
38
|
+
key: d,
|
|
39
|
+
relatedKey: s[c - 1] ?? "",
|
|
40
|
+
callback: () => p
|
|
41
|
+
}), c += 1;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (!o.has(l)) {
|
|
45
|
+
r.push({
|
|
46
|
+
type: b.DELETE,
|
|
47
|
+
key: l,
|
|
48
|
+
relatedKey: "",
|
|
49
|
+
callback: S
|
|
50
|
+
}), i += 1;
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
const f = n.positions.indexOf(
|
|
54
|
+
d,
|
|
55
|
+
i
|
|
56
|
+
), g = n.positions[i];
|
|
57
|
+
r.push({
|
|
58
|
+
type: b.MOVE,
|
|
59
|
+
key: d,
|
|
60
|
+
relatedKey: g,
|
|
61
|
+
callback: S
|
|
62
|
+
}), n.positions[i] = n.positions[f], n.positions[f] = g, c += 1, i += 1;
|
|
63
|
+
}
|
|
64
|
+
return n.keys = o, n.positions = s, r;
|
|
65
|
+
}, ct = (t, e, n) => {
|
|
66
|
+
const { signal: r } = n, s = /* @__PURE__ */ new Map(), o = {
|
|
67
|
+
keys: /* @__PURE__ */ new Set(),
|
|
68
|
+
positions: []
|
|
69
|
+
}, a = Y(
|
|
70
|
+
t,
|
|
71
|
+
e,
|
|
72
|
+
n
|
|
73
|
+
), c = W(t), [i] = _(t, "list"), { beforeRender: u, afterRender: d } = B(
|
|
74
|
+
t,
|
|
75
|
+
n
|
|
76
|
+
);
|
|
77
|
+
r.computed((l) => {
|
|
78
|
+
const f = e.activeValue(), g = st(f) ? Array.from(f) : [f], p = ot(
|
|
79
|
+
g,
|
|
80
|
+
e.keyFn,
|
|
81
|
+
o
|
|
82
|
+
);
|
|
83
|
+
l && u(f), p.forEach(({ type: m, key: h, relatedKey: O, callback: k }) => {
|
|
84
|
+
switch (m) {
|
|
85
|
+
case b.ADD:
|
|
86
|
+
const C = [
|
|
87
|
+
new Comment(`list-${h}-start`),
|
|
88
|
+
new Comment(`list-${h}-end`)
|
|
89
|
+
];
|
|
90
|
+
s.set(h, C), (s.get(O)?.[1] ?? i).after(...C);
|
|
91
|
+
const w = { activeValue: k, keyFn: e.keyFn }, { status: x } = z(
|
|
92
|
+
c,
|
|
93
|
+
a,
|
|
94
|
+
w,
|
|
95
|
+
n
|
|
96
|
+
);
|
|
97
|
+
r.computed(() => {
|
|
98
|
+
const F = v(
|
|
99
|
+
c[x()].cloneNode(!0),
|
|
100
|
+
w,
|
|
101
|
+
n
|
|
102
|
+
);
|
|
103
|
+
requestAnimationFrame(() => {
|
|
104
|
+
A(...C), C[0].after(F);
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
break;
|
|
108
|
+
case b.DELETE:
|
|
109
|
+
const [L, nt] = s.get(h);
|
|
110
|
+
requestAnimationFrame(() => {
|
|
111
|
+
A(L.previousSibling, nt.nextSibling), s.delete(h);
|
|
112
|
+
});
|
|
113
|
+
break;
|
|
114
|
+
case b.MOVE:
|
|
115
|
+
const [$, V] = s.get(O), [D, j] = s.get(h);
|
|
116
|
+
requestAnimationFrame(() => {
|
|
117
|
+
const F = A($, V), rt = A(D, j);
|
|
118
|
+
$.after(rt), D.after(F);
|
|
119
|
+
}), s.set(O, [D, j]), s.set(h, [$, V]);
|
|
120
|
+
break;
|
|
121
|
+
default:
|
|
122
|
+
console.warn("operation not recognized");
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
}), l && requestAnimationFrame(() => {
|
|
126
|
+
d(f);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
}, at = (t, e, n) => {
|
|
130
|
+
const { signal: r, values: s } = n, o = s.get(t.getAttribute("data-replace")), [a, c] = _(t, "content");
|
|
131
|
+
r.computed((i) => {
|
|
132
|
+
const u = o(e.activeValue()), d = document.createTextNode(u);
|
|
133
|
+
i ? requestAnimationFrame(() => {
|
|
134
|
+
A(a, c), a.after(d);
|
|
135
|
+
}) : (A(a, c), a.after(d));
|
|
136
|
+
});
|
|
137
|
+
}, it = (t, e) => {
|
|
138
|
+
const { signal: n, values: r } = e;
|
|
139
|
+
t.getAttributeNames().forEach((s) => {
|
|
140
|
+
if (!r.has(s))
|
|
141
|
+
return;
|
|
142
|
+
t.removeAttribute(s);
|
|
143
|
+
const o = t.getRootNode().host, a = r.get(s);
|
|
144
|
+
n.computed(() => {
|
|
145
|
+
const c = a();
|
|
146
|
+
o.style.setProperty(`--${s}`, c), n.onCleanup(() => o.style.removeProperty(`--${s}`));
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
}, lt = (t) => {
|
|
150
|
+
const e = [];
|
|
151
|
+
let n = t.indexOf("__");
|
|
152
|
+
for (; n !== -1; ) {
|
|
153
|
+
const r = t.indexOf("__", n + 2);
|
|
154
|
+
if (r === -1) break;
|
|
155
|
+
e.push(t.slice(n, r + 2)), n = t.indexOf("__", r + 2);
|
|
156
|
+
}
|
|
157
|
+
return e;
|
|
158
|
+
}, ut = (t, e, n) => {
|
|
159
|
+
const { signal: r, values: s } = n;
|
|
160
|
+
t.removeAttribute("data-update"), t.getAttributeNames().forEach((o) => {
|
|
161
|
+
const a = t.getAttribute(o), c = s.get(a);
|
|
162
|
+
if (!(!o.startsWith("__") && !a.includes("__"))) {
|
|
163
|
+
if (o === "ref") {
|
|
164
|
+
t.removeAttribute(o), c(t);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (o.startsWith("on")) {
|
|
168
|
+
t.removeAttribute(o);
|
|
169
|
+
const i = o.slice(2);
|
|
170
|
+
t.addEventListener(i, c), r.onCleanup(
|
|
171
|
+
() => t.removeEventListener(
|
|
172
|
+
i,
|
|
173
|
+
c
|
|
174
|
+
)
|
|
175
|
+
);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (o === "class") {
|
|
179
|
+
lt(a).forEach((i) => {
|
|
180
|
+
const u = s.get(i);
|
|
181
|
+
let d = i;
|
|
182
|
+
r.computed(() => {
|
|
183
|
+
const l = u(e.activeValue());
|
|
184
|
+
t.classList.replace(d, l), d = l;
|
|
185
|
+
});
|
|
186
|
+
});
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (t.tagName.includes("-")) {
|
|
190
|
+
t.hasOwnProperty("setProperty") ? t.setProperty(o, c) : t[o] = c;
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
typeof c == "function" && (t.removeAttribute(o), r.computed(() => {
|
|
194
|
+
const i = c(e.activeValue());
|
|
195
|
+
t.setAttribute(
|
|
196
|
+
o || i,
|
|
197
|
+
o ? i : ""
|
|
198
|
+
);
|
|
199
|
+
}));
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}, dt = (t) => {
|
|
203
|
+
if (t instanceof HTMLTemplateElement)
|
|
204
|
+
return t;
|
|
205
|
+
const e = document.createElement("template");
|
|
206
|
+
return t.replaceWith(e), e.content.append(t), e;
|
|
207
|
+
}, v = (t, e, n) => (t.querySelectorAll("[slot='item']").forEach((r) => {
|
|
208
|
+
r.removeAttribute("slot"), ct(dt(r), e, n);
|
|
209
|
+
}), t.querySelectorAll("template").forEach((r) => {
|
|
210
|
+
ft(r, e, n);
|
|
211
|
+
}), t.querySelectorAll("[data-update]").forEach((r) => {
|
|
212
|
+
ut(r, e, n);
|
|
213
|
+
}), t.querySelectorAll("[data-replace]").forEach(
|
|
214
|
+
(r) => at(r, e, n)
|
|
215
|
+
), t.querySelectorAll("style").forEach((r) => it(r, n)), t), T = (t, e) => {
|
|
216
|
+
const n = document.createDocumentFragment();
|
|
217
|
+
return t.content.querySelectorAll(`[slot=${e}]`).forEach((r) => {
|
|
218
|
+
n.append(r);
|
|
219
|
+
}), n;
|
|
220
|
+
}, U = () => !0, S = () => {
|
|
221
|
+
}, I = (t, e, n) => `key-${t.toString()}`, y = {
|
|
222
|
+
CONTENT: 0,
|
|
223
|
+
FALLBACK: 1,
|
|
224
|
+
EMPTY: 2,
|
|
225
|
+
LOADING: 3,
|
|
226
|
+
ERROR: 4
|
|
227
|
+
}, W = (t) => {
|
|
228
|
+
const e = t.cloneNode(!0);
|
|
229
|
+
return {
|
|
230
|
+
[y.CONTENT]: e.content,
|
|
231
|
+
[y.FALLBACK]: T(e, "fallback"),
|
|
232
|
+
[y.EMPTY]: T(e, "empty"),
|
|
233
|
+
[y.LOADING]: T(e, "loading"),
|
|
234
|
+
[y.ERROR]: T(e, "error")
|
|
235
|
+
};
|
|
236
|
+
}, Y = (t, { keyFn: e }, { values: n }) => ({
|
|
237
|
+
when: n.get(t.getAttribute("when")) ?? U,
|
|
238
|
+
each: n.get(t.getAttribute("each")) ?? S,
|
|
239
|
+
//@ts-expect-error
|
|
240
|
+
suspense: n.get(
|
|
241
|
+
t.getAttribute("suspense")
|
|
242
|
+
) ?? S,
|
|
243
|
+
ref: n.get(t.getAttribute("ref")) ?? S,
|
|
244
|
+
keyFn: n.get(t.getAttribute("keys")) ?? e ?? I
|
|
245
|
+
}), _ = (t, e = "template") => {
|
|
246
|
+
const n = new Comment(`${e}-start`), r = new Comment(`${e}-end`);
|
|
247
|
+
return t.replaceWith(n, r), [n, r];
|
|
248
|
+
}, z = (t, e, { activeValue: n }, r) => {
|
|
249
|
+
const s = t[y.EMPTY].childNodes.length, o = t[y.ERROR].childNodes.length, a = t[y.LOADING].childNodes.length, [c, i] = r.signal.create(void 0);
|
|
250
|
+
let u;
|
|
251
|
+
return { status: r.signal.computed(() => {
|
|
252
|
+
try {
|
|
253
|
+
const l = n(), f = e.when(l), g = e.each?.(l), p = e.suspense?.status?.(), m = e.suspense?.error?.(), h = e.suspense?.(l);
|
|
254
|
+
return u = m ?? h ?? g ?? f, i(u), p === R.ERROR && o ? y.ERROR : p === R.LOADING && a ? y.LOADING : g?.length === 0 && s ? y.EMPTY : !f || p && p !== R.SUCCESS ? y.FALLBACK : y.CONTENT;
|
|
255
|
+
} catch {
|
|
256
|
+
return y.ERROR;
|
|
257
|
+
}
|
|
258
|
+
}), result: c, staticResult: () => u };
|
|
259
|
+
}, B = (t, e) => {
|
|
260
|
+
const n = {
|
|
261
|
+
beforeRender: S,
|
|
262
|
+
afterRender: S
|
|
263
|
+
};
|
|
264
|
+
return t.getAttributeNames().forEach((r) => {
|
|
265
|
+
switch (r.toLowerCase()) {
|
|
266
|
+
case "beforerender":
|
|
267
|
+
n.beforeRender = e.values.get(
|
|
268
|
+
t.getAttribute(r)
|
|
269
|
+
);
|
|
270
|
+
break;
|
|
271
|
+
case "afterrender":
|
|
272
|
+
n.afterRender = e.values.get(
|
|
273
|
+
t.getAttribute(r)
|
|
274
|
+
);
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
}), n;
|
|
278
|
+
}, ft = (t, e, n) => {
|
|
279
|
+
const { signal: r } = n, s = Y(
|
|
280
|
+
t,
|
|
281
|
+
e,
|
|
282
|
+
n
|
|
283
|
+
), o = W(t), [a, c] = _(t), { beforeRender: i, afterRender: u } = B(
|
|
284
|
+
t,
|
|
285
|
+
n
|
|
286
|
+
), { result: d, status: l, staticResult: f } = z(
|
|
287
|
+
o,
|
|
288
|
+
s,
|
|
289
|
+
e,
|
|
290
|
+
n
|
|
291
|
+
);
|
|
292
|
+
r.computed((g) => {
|
|
293
|
+
const p = f(), m = v(
|
|
294
|
+
o[l()].cloneNode(!0),
|
|
295
|
+
{ activeValue: d, keyFn: s.keyFn },
|
|
296
|
+
n
|
|
297
|
+
);
|
|
298
|
+
g ? (i(p), requestAnimationFrame(() => {
|
|
299
|
+
A(a, c), a.after(m), u(p);
|
|
300
|
+
})) : (A(a, c), a.after(m));
|
|
301
|
+
});
|
|
302
|
+
}, R = {
|
|
303
|
+
IDLE: -1,
|
|
304
|
+
ERROR: 0,
|
|
305
|
+
LOADING: 1,
|
|
306
|
+
SUCCESS: 2
|
|
307
|
+
}, H = (t) => {
|
|
308
|
+
for (const e of t.dependencies)
|
|
309
|
+
e.delete(t);
|
|
310
|
+
t.children.forEach(H), t.cleanupEffects.forEach((e) => e()), t.dependencies.clear(), t.children.clear(), t.cleanupEffects.clear(), t.parent = void 0;
|
|
311
|
+
}, pt = (t) => {
|
|
312
|
+
let e = t;
|
|
313
|
+
for (; e; ) {
|
|
314
|
+
if (e.dirty) return !0;
|
|
315
|
+
e = e.parent;
|
|
316
|
+
}
|
|
317
|
+
return !1;
|
|
318
|
+
}, ht = () => {
|
|
319
|
+
const t = [], e = (c) => {
|
|
320
|
+
const i = /* @__PURE__ */ new Set();
|
|
321
|
+
let u = c;
|
|
322
|
+
return [() => {
|
|
323
|
+
const f = t.at(-1);
|
|
324
|
+
return f && (i.add(f), f.dependencies.add(i)), u;
|
|
325
|
+
}, (f) => {
|
|
326
|
+
const g = typeof f == "function" ? f(u) : f;
|
|
327
|
+
g !== u && (u = g, [...i].forEach((p) => {
|
|
328
|
+
p.dependencies.size > 0 ? (p.dirty = !0, p.execute()) : i.delete(p);
|
|
329
|
+
}));
|
|
330
|
+
}];
|
|
331
|
+
}, n = ([
|
|
332
|
+
c,
|
|
333
|
+
i
|
|
334
|
+
]) => {
|
|
335
|
+
const u = /* @__PURE__ */ new Set();
|
|
336
|
+
return [() => {
|
|
337
|
+
const l = t.at(-1);
|
|
338
|
+
return l && (u.add(l), l.dependencies.add(u)), c();
|
|
339
|
+
}, i];
|
|
340
|
+
}, r = (c) => {
|
|
341
|
+
t.at(-1)?.cleanupEffects.add(c);
|
|
342
|
+
}, s = (c) => {
|
|
343
|
+
const [i, u] = e(void 0), d = t.at(-1), l = {
|
|
344
|
+
execute() {
|
|
345
|
+
H(l), t.push(l), u(c(pt(l))), t.pop(), l.dirty = !1, !(!l.parent || l.dependencies.size > 0) && (l.children.forEach((f) => {
|
|
346
|
+
d.children.add(f), f.parent = d, d.cleanupEffects = d.cleanupEffects.union(
|
|
347
|
+
l.cleanupEffects
|
|
348
|
+
);
|
|
349
|
+
}), l.children.clear(), l.parent = void 0);
|
|
350
|
+
},
|
|
351
|
+
dependencies: /* @__PURE__ */ new Set(),
|
|
352
|
+
parent: d,
|
|
353
|
+
children: /* @__PURE__ */ new Set(),
|
|
354
|
+
cleanupEffects: /* @__PURE__ */ new Set(),
|
|
355
|
+
dirty: !1
|
|
356
|
+
};
|
|
357
|
+
return d && d.children.add(l), l.execute(), i;
|
|
358
|
+
};
|
|
359
|
+
return {
|
|
360
|
+
create: e,
|
|
361
|
+
createAsync: (c, i = U) => {
|
|
362
|
+
const [u, d] = e(void 0), [l, f] = e(void 0), [g, p] = e(
|
|
363
|
+
R.IDLE
|
|
364
|
+
);
|
|
365
|
+
let m = c, h = null;
|
|
366
|
+
const O = () => {
|
|
367
|
+
(!h || h.signal.aborted) && (h = new AbortController());
|
|
368
|
+
}, k = async (E) => {
|
|
369
|
+
O();
|
|
370
|
+
let w = !1;
|
|
371
|
+
const x = () => {
|
|
372
|
+
console.log("aborted"), w = !0;
|
|
373
|
+
};
|
|
374
|
+
h.signal.addEventListener("abort", x, { once: !0 });
|
|
375
|
+
try {
|
|
376
|
+
p(R.LOADING);
|
|
377
|
+
const L = await E(i());
|
|
378
|
+
w || (d(L), p(R.SUCCESS));
|
|
379
|
+
} catch (L) {
|
|
380
|
+
w || (p(R.ERROR), f(L));
|
|
381
|
+
} finally {
|
|
382
|
+
h.signal.removeEventListener("abort", x);
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
s(() => {
|
|
386
|
+
i() && (h?.abort("triggered"), k(m));
|
|
387
|
+
});
|
|
388
|
+
const C = (E) => {
|
|
389
|
+
typeof E == "function" ? (m = Promise.try(E), k(m)) : d(E);
|
|
390
|
+
};
|
|
391
|
+
return u.error = l, u.status = g, u.refetch = () => {
|
|
392
|
+
h?.abort("refetch"), k(m);
|
|
393
|
+
}, [u, C];
|
|
394
|
+
},
|
|
395
|
+
computed: s,
|
|
396
|
+
onCleanup: r,
|
|
397
|
+
context: t,
|
|
398
|
+
ref: () => {
|
|
399
|
+
const c = [];
|
|
400
|
+
return (...u) => {
|
|
401
|
+
if (u.length === 2) {
|
|
402
|
+
c.length = 0;
|
|
403
|
+
const [d, l] = u;
|
|
404
|
+
let f = d.nextSibling;
|
|
405
|
+
for (; f && f !== l; ) {
|
|
406
|
+
const g = f.nextSibling;
|
|
407
|
+
c.push(f), f = g;
|
|
408
|
+
}
|
|
409
|
+
return c;
|
|
410
|
+
}
|
|
411
|
+
return u.length === 1 ? (c.length = 0, c.push(u.at(0)), c.at(0)) : c.length > 1 ? c : c.at(0);
|
|
412
|
+
};
|
|
413
|
+
},
|
|
414
|
+
fromSignal: n,
|
|
415
|
+
dispose() {
|
|
416
|
+
t.length = 0;
|
|
417
|
+
}
|
|
418
|
+
};
|
|
419
|
+
}, gt = (t, e) => {
|
|
420
|
+
const n = /* @__PURE__ */ new WeakMap(), r = (s) => {
|
|
421
|
+
let o = !1, a = !0;
|
|
422
|
+
const [c, i] = e.create(s.assignedNodes()), u = () => {
|
|
423
|
+
if (!o) {
|
|
424
|
+
if (a) {
|
|
425
|
+
a = !1;
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
o = !0, i(s.assignedNodes()), requestAnimationFrame(() => {
|
|
429
|
+
o = !1;
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
return s.addEventListener("slotchange", u), e.onCleanup(() => {
|
|
434
|
+
s.removeEventListener("slotchange", u);
|
|
435
|
+
}), c;
|
|
436
|
+
};
|
|
437
|
+
return (s = "") => {
|
|
438
|
+
const o = s ? `slot[name='${s}']` : "slot:not([name])", a = t.querySelector(o);
|
|
439
|
+
if (!a)
|
|
440
|
+
return console.error("no slot with that name exists, returning empty signal"), () => [];
|
|
441
|
+
if (n.has(a))
|
|
442
|
+
return n.get(a);
|
|
443
|
+
const c = r(a);
|
|
444
|
+
return n.set(a, c), c;
|
|
445
|
+
};
|
|
446
|
+
}, yt = (t, { mountCallbacks: e, unMountCallbacks: n, signal: r }) => ({
|
|
447
|
+
signal: r,
|
|
448
|
+
lifecyle: {
|
|
449
|
+
onMount: (s) => {
|
|
450
|
+
e.add(s);
|
|
451
|
+
},
|
|
452
|
+
onUnmount: (s) => {
|
|
453
|
+
n.add(s);
|
|
454
|
+
}
|
|
455
|
+
},
|
|
456
|
+
elements: {
|
|
457
|
+
shadowRoot: () => t,
|
|
458
|
+
slots: gt(t, r)
|
|
459
|
+
}
|
|
460
|
+
}), mt = () => {
|
|
461
|
+
const t = ht(), e = /* @__PURE__ */ new Set(), n = /* @__PURE__ */ new Set();
|
|
462
|
+
return {
|
|
463
|
+
signal: t,
|
|
464
|
+
mountCallbacks: e,
|
|
465
|
+
unMountCallbacks: n,
|
|
466
|
+
values: /* @__PURE__ */ new Map(),
|
|
467
|
+
dispose() {
|
|
468
|
+
t.dispose(), e.clear(), n.clear();
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
}, J = Symbol("render"), At = (t) => {
|
|
472
|
+
const e = t.lastIndexOf("<"), n = t.lastIndexOf(">"), r = n === -1;
|
|
473
|
+
return e === -1 ? !1 : r || n < e;
|
|
474
|
+
}, St = ["string", "number", "bigint", "boolean", "symbol"], q = (t) => St.includes(typeof t), Et = (t) => typeof t == "object" && t?.key === J, Q = () => `__${(Math.random() * 1e5).toFixed()}__`, M = (t, e) => (t.forEach((n, r) => e.set(r, n)), e), X = Symbol("css"), Z = () => `css-${(Math.random() * 1e5).toFixed()}`, bt = (t) => t.template.at(-1) === ".", K = (t) => typeof t == "object" && t?.key === X, N = (t, e) => {
|
|
475
|
+
if (q(t))
|
|
476
|
+
return t.toString();
|
|
477
|
+
if (Array.isArray(t) || t instanceof Set)
|
|
478
|
+
return Array.from(t).map((n) => N(n, e)).join(" ");
|
|
479
|
+
if (K(t))
|
|
480
|
+
return M(t.values, e.values), bt(e) ? (e.values.set(t.name, t.template), t.name) : t.template;
|
|
481
|
+
if (typeof t == "function") {
|
|
482
|
+
const n = Z();
|
|
483
|
+
return e.values.set(n, t), `var(--${n}, ${t()})`;
|
|
484
|
+
}
|
|
485
|
+
return typeof t == "function" ? N(t(), e) : t ? t.toString() : "";
|
|
486
|
+
}, Rt = (t, ...e) => {
|
|
487
|
+
const n = {
|
|
488
|
+
template: t[0],
|
|
489
|
+
values: /* @__PURE__ */ new Map(),
|
|
490
|
+
key: X,
|
|
491
|
+
name: Z()
|
|
492
|
+
};
|
|
493
|
+
return t.slice(1).forEach((r, s) => {
|
|
494
|
+
const o = e[s];
|
|
495
|
+
n.template += `${N(o, n)}${r}`;
|
|
496
|
+
}), n;
|
|
497
|
+
}, Ct = (t) => {
|
|
498
|
+
const e = t.template, n = e.lastIndexOf("<");
|
|
499
|
+
if (e.indexOf(" data-update ", n) !== -1)
|
|
500
|
+
return;
|
|
501
|
+
const r = e.indexOf(" ", n), s = e.slice(0, r), o = e.slice(r + 1);
|
|
502
|
+
t.template = `${s} data-update ${o}`;
|
|
503
|
+
}, P = (t, e) => {
|
|
504
|
+
if (q(t))
|
|
505
|
+
return t;
|
|
506
|
+
if (K(t))
|
|
507
|
+
return M(t.values, e.values), e.values.set(t.name, t.template), t.name;
|
|
508
|
+
if (Array.isArray(t) || t instanceof Set)
|
|
509
|
+
return Array.from(t).map((r) => P(r, e)).join(" ");
|
|
510
|
+
if (t && typeof t == "object")
|
|
511
|
+
return (t instanceof Map ? Array.from(t) : Object.entries(t)).map(
|
|
512
|
+
([s, o]) => `${s}=${P(o, e)} `
|
|
513
|
+
).join(" ");
|
|
514
|
+
Ct(e);
|
|
515
|
+
const n = Q();
|
|
516
|
+
return e.values.set(n, t), n;
|
|
517
|
+
}, wt = (t, e) => {
|
|
518
|
+
if (q(t))
|
|
519
|
+
return t;
|
|
520
|
+
if (Et(t))
|
|
521
|
+
return M(t.values, e.values), t.template;
|
|
522
|
+
if (K(t))
|
|
523
|
+
return M(t.values, e.values), e.values.set(t.name, t.template), `<style ${Array.from(t.values.keys()).join(" ")}>${t.template}</style>`;
|
|
524
|
+
const n = Q();
|
|
525
|
+
return e.values.set(n, t), `<span data-replace=${n}></span>`;
|
|
526
|
+
}, tt = (t, ...e) => {
|
|
527
|
+
const n = {
|
|
528
|
+
template: t[0],
|
|
529
|
+
values: /* @__PURE__ */ new Map(),
|
|
530
|
+
key: J,
|
|
531
|
+
name: ""
|
|
532
|
+
};
|
|
533
|
+
return t.slice(1).forEach((r, s) => {
|
|
534
|
+
const o = e[s], a = At(n.template) ? P(o, n) : wt(o, n);
|
|
535
|
+
n.template += `${a}${r}`;
|
|
536
|
+
}), n;
|
|
537
|
+
}, G = (t) => {
|
|
538
|
+
try {
|
|
539
|
+
t();
|
|
540
|
+
} catch (e) {
|
|
541
|
+
console.warn(e);
|
|
542
|
+
}
|
|
543
|
+
}, et = (t, e, n = {}) => {
|
|
544
|
+
class r extends HTMLElement {
|
|
545
|
+
#t = /* @__PURE__ */ new Map();
|
|
546
|
+
#e = mt();
|
|
547
|
+
#n;
|
|
548
|
+
#r;
|
|
549
|
+
constructor() {
|
|
550
|
+
super(), this.attachShadow({ mode: "open", serializable: !0 }), Array.from(this.attributes).forEach((o) => {
|
|
551
|
+
this.#t.set(o.name, o.value);
|
|
552
|
+
});
|
|
553
|
+
}
|
|
554
|
+
connectedCallback() {
|
|
555
|
+
this.#s(), this.#e.mountCallbacks.forEach(G), this.#c();
|
|
556
|
+
}
|
|
557
|
+
async disconnectedCallback() {
|
|
558
|
+
await Promise.resolve(), this.isConnected || (this.#n?.disconnect(), this.#e.unMountCallbacks.forEach(G), this.#t.clear(), this.#e.dispose());
|
|
559
|
+
}
|
|
560
|
+
setProperty(o, a) {
|
|
561
|
+
o === "style" || this.#t.get(o) === a || (a == null ? this.#t.delete(o) : this.#t.set(o, a), this.#o());
|
|
562
|
+
}
|
|
563
|
+
#o() {
|
|
564
|
+
this.#r && cancelAnimationFrame(this.#r), this.#r = requestAnimationFrame(() => {
|
|
565
|
+
this.#s(), this.#r = null;
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
#c() {
|
|
569
|
+
this.#n?.disconnect(), this.#n = new MutationObserver((o) => {
|
|
570
|
+
o.forEach((a) => {
|
|
571
|
+
this.setProperty(
|
|
572
|
+
a.attributeName,
|
|
573
|
+
this.getAttribute(a.attributeName)
|
|
574
|
+
);
|
|
575
|
+
});
|
|
576
|
+
}), this.#n.observe(this, { attributes: !0 });
|
|
577
|
+
}
|
|
578
|
+
#s() {
|
|
579
|
+
const { template: o, values: a } = e(
|
|
580
|
+
Object.fromEntries(this.#t),
|
|
581
|
+
yt(this.shadowRoot, this.#e)
|
|
582
|
+
), c = new Range().createContextualFragment(o);
|
|
583
|
+
this.#e.values = a;
|
|
584
|
+
const i = v(
|
|
585
|
+
c,
|
|
586
|
+
{
|
|
587
|
+
activeValue: () => {
|
|
588
|
+
},
|
|
589
|
+
keyFn: I
|
|
590
|
+
},
|
|
591
|
+
this.#e
|
|
592
|
+
);
|
|
593
|
+
this.shadowRoot.replaceChildren(i);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return customElements?.get(t) || customElements.define(t, r), (s = {}) => tt`<${t} ${{ ...s }}></${t}>`;
|
|
597
|
+
};
|
|
598
|
+
et.html = tt;
|
|
599
|
+
et.css = Rt;
|
|
600
|
+
export {
|
|
601
|
+
et as render
|
|
602
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(C,k){typeof exports=="object"&&typeof module<"u"?k(exports):typeof define=="function"&&define.amd?define(["exports"],k):(C=typeof globalThis<"u"?globalThis:C||self,k(C.grundlage={}))})(this,function(C){"use strict";const k=t=>!!t?.[Symbol.iterator],S=(t,e)=>{const n=new DocumentFragment;let r=t.nextSibling;for(;r&&r!==e;){const s=r.nextSibling;n.append(r),r=s}return n},E={ADD:0,DELETE:1,MOVE:2},st=(t,e=N,n)=>{const r=[],s=t.map(e),o=new Set(s),a=Math.max(s.length,n.positions.length);let c=0,i=0;for(let u=0;u<a;u++){const d=s[c],l=n.positions[i];if(d===l){c+=1,i+=1;continue}if(!d){r.push({type:E.DELETE,key:l,relatedKey:"",callback:A}),i+=1;continue}if(!n.keys.has(d)){const p=t[c];r.push({type:E.ADD,key:d,relatedKey:s[c-1]??"",callback:()=>p}),c+=1;continue}if(!o.has(l)){r.push({type:E.DELETE,key:l,relatedKey:"",callback:A}),i+=1;continue}const f=n.positions.indexOf(d,i),g=n.positions[i];r.push({type:E.MOVE,key:d,relatedKey:g,callback:A}),n.positions[i]=n.positions[f],n.positions[f]=g,c+=1,i+=1}return n.keys=o,n.positions=s,r},ot=(t,e,n)=>{const{signal:r}=n,s=new Map,o={keys:new Set,positions:[]},a=Y(t,e,n),c=W(t),[i]=P(t,"list"),{beforeRender:u,afterRender:d}=B(t,n);r.computed(l=>{const f=e.activeValue(),g=k(f)?Array.from(f):[f],p=st(g,e.keyFn,o);l&&u(f),p.forEach(({type:m,key:h,relatedKey:T,callback:x})=>{switch(m){case E.ADD:const O=[new Comment(`list-${h}-start`),new Comment(`list-${h}-end`)];s.set(h,O),(s.get(T)?.[1]??i).after(...O);const w={activeValue:x,keyFn:e.keyFn},{status:D}=z(c,a,w,n);r.computed(()=>{const G=F(c[D()].cloneNode(!0),w,n);requestAnimationFrame(()=>{S(...O),O[0].after(G)})});break;case E.DELETE:const[L,Ot]=s.get(h);requestAnimationFrame(()=>{S(L.previousSibling,Ot.nextSibling),s.delete(h)});break;case E.MOVE:const[j,nt]=s.get(T),[V,rt]=s.get(h);requestAnimationFrame(()=>{const G=S(j,nt),wt=S(V,rt);j.after(wt),V.after(G)}),s.set(T,[V,rt]),s.set(h,[j,nt]);break;default:console.warn("operation not recognized");break}}),l&&requestAnimationFrame(()=>{d(f)})})},ct=(t,e,n)=>{const{signal:r,values:s}=n,o=s.get(t.getAttribute("data-replace")),[a,c]=P(t,"content");r.computed(i=>{const u=o(e.activeValue()),d=document.createTextNode(u);i?requestAnimationFrame(()=>{S(a,c),a.after(d)}):(S(a,c),a.after(d))})},at=(t,e)=>{const{signal:n,values:r}=e;t.getAttributeNames().forEach(s=>{if(!r.has(s))return;t.removeAttribute(s);const o=t.getRootNode().host,a=r.get(s);n.computed(()=>{const c=a();o.style.setProperty(`--${s}`,c),n.onCleanup(()=>o.style.removeProperty(`--${s}`))})})},it=t=>{const e=[];let n=t.indexOf("__");for(;n!==-1;){const r=t.indexOf("__",n+2);if(r===-1)break;e.push(t.slice(n,r+2)),n=t.indexOf("__",r+2)}return e},lt=(t,e,n)=>{const{signal:r,values:s}=n;t.removeAttribute("data-update"),t.getAttributeNames().forEach(o=>{const a=t.getAttribute(o),c=s.get(a);if(!(!o.startsWith("__")&&!a.includes("__"))){if(o==="ref"){t.removeAttribute(o),c(t);return}if(o.startsWith("on")){t.removeAttribute(o);const i=o.slice(2);t.addEventListener(i,c),r.onCleanup(()=>t.removeEventListener(i,c));return}if(o==="class"){it(a).forEach(i=>{const u=s.get(i);let d=i;r.computed(()=>{const l=u(e.activeValue());t.classList.replace(d,l),d=l})});return}if(t.tagName.includes("-")){t.hasOwnProperty("setProperty")?t.setProperty(o,c):t[o]=c;return}typeof c=="function"&&(t.removeAttribute(o),r.computed(()=>{const i=c(e.activeValue());t.setAttribute(o||i,o?i:"")}))}})},ut=t=>{if(t instanceof HTMLTemplateElement)return t;const e=document.createElement("template");return t.replaceWith(e),e.content.append(t),e},F=(t,e,n)=>(t.querySelectorAll("[slot='item']").forEach(r=>{r.removeAttribute("slot"),ot(ut(r),e,n)}),t.querySelectorAll("template").forEach(r=>{dt(r,e,n)}),t.querySelectorAll("[data-update]").forEach(r=>{lt(r,e,n)}),t.querySelectorAll("[data-replace]").forEach(r=>ct(r,e,n)),t.querySelectorAll("style").forEach(r=>at(r,n)),t),M=(t,e)=>{const n=document.createDocumentFragment();return t.content.querySelectorAll(`[slot=${e}]`).forEach(r=>{n.append(r)}),n},U=()=>!0,A=()=>{},N=(t,e,n)=>`key-${t.toString()}`,y={CONTENT:0,FALLBACK:1,EMPTY:2,LOADING:3,ERROR:4},W=t=>{const e=t.cloneNode(!0);return{[y.CONTENT]:e.content,[y.FALLBACK]:M(e,"fallback"),[y.EMPTY]:M(e,"empty"),[y.LOADING]:M(e,"loading"),[y.ERROR]:M(e,"error")}},Y=(t,{keyFn:e},{values:n})=>({when:n.get(t.getAttribute("when"))??U,each:n.get(t.getAttribute("each"))??A,suspense:n.get(t.getAttribute("suspense"))??A,ref:n.get(t.getAttribute("ref"))??A,keyFn:n.get(t.getAttribute("keys"))??e??N}),P=(t,e="template")=>{const n=new Comment(`${e}-start`),r=new Comment(`${e}-end`);return t.replaceWith(n,r),[n,r]},z=(t,e,{activeValue:n},r)=>{const s=t[y.EMPTY].childNodes.length,o=t[y.ERROR].childNodes.length,a=t[y.LOADING].childNodes.length,[c,i]=r.signal.create(void 0);let u;return{status:r.signal.computed(()=>{try{const l=n(),f=e.when(l),g=e.each?.(l),p=e.suspense?.status?.(),m=e.suspense?.error?.(),h=e.suspense?.(l);return u=m??h??g??f,i(u),p===b.ERROR&&o?y.ERROR:p===b.LOADING&&a?y.LOADING:g?.length===0&&s?y.EMPTY:!f||p&&p!==b.SUCCESS?y.FALLBACK:y.CONTENT}catch{return y.ERROR}}),result:c,staticResult:()=>u}},B=(t,e)=>{const n={beforeRender:A,afterRender:A};return t.getAttributeNames().forEach(r=>{switch(r.toLowerCase()){case"beforerender":n.beforeRender=e.values.get(t.getAttribute(r));break;case"afterrender":n.afterRender=e.values.get(t.getAttribute(r));break}}),n},dt=(t,e,n)=>{const{signal:r}=n,s=Y(t,e,n),o=W(t),[a,c]=P(t),{beforeRender:i,afterRender:u}=B(t,n),{result:d,status:l,staticResult:f}=z(o,s,e,n);r.computed(g=>{const p=f(),m=F(o[l()].cloneNode(!0),{activeValue:d,keyFn:s.keyFn},n);g?(i(p),requestAnimationFrame(()=>{S(a,c),a.after(m),u(p)})):(S(a,c),a.after(m))})},b={IDLE:-1,ERROR:0,LOADING:1,SUCCESS:2},H=t=>{for(const e of t.dependencies)e.delete(t);t.children.forEach(H),t.cleanupEffects.forEach(e=>e()),t.dependencies.clear(),t.children.clear(),t.cleanupEffects.clear(),t.parent=void 0},ft=t=>{let e=t;for(;e;){if(e.dirty)return!0;e=e.parent}return!1},pt=()=>{const t=[],e=c=>{const i=new Set;let u=c;return[()=>{const f=t.at(-1);return f&&(i.add(f),f.dependencies.add(i)),u},f=>{const g=typeof f=="function"?f(u):f;g!==u&&(u=g,[...i].forEach(p=>{p.dependencies.size>0?(p.dirty=!0,p.execute()):i.delete(p)}))}]},n=([c,i])=>{const u=new Set;return[()=>{const l=t.at(-1);return l&&(u.add(l),l.dependencies.add(u)),c()},i]},r=c=>{t.at(-1)?.cleanupEffects.add(c)},s=c=>{const[i,u]=e(void 0),d=t.at(-1),l={execute(){H(l),t.push(l),u(c(ft(l))),t.pop(),l.dirty=!1,!(!l.parent||l.dependencies.size>0)&&(l.children.forEach(f=>{d.children.add(f),f.parent=d,d.cleanupEffects=d.cleanupEffects.union(l.cleanupEffects)}),l.children.clear(),l.parent=void 0)},dependencies:new Set,parent:d,children:new Set,cleanupEffects:new Set,dirty:!1};return d&&d.children.add(l),l.execute(),i};return{create:e,createAsync:(c,i=U)=>{const[u,d]=e(void 0),[l,f]=e(void 0),[g,p]=e(b.IDLE);let m=c,h=null;const T=()=>{(!h||h.signal.aborted)&&(h=new AbortController)},x=async R=>{T();let w=!1;const D=()=>{console.log("aborted"),w=!0};h.signal.addEventListener("abort",D,{once:!0});try{p(b.LOADING);const L=await R(i());w||(d(L),p(b.SUCCESS))}catch(L){w||(p(b.ERROR),f(L))}finally{h.signal.removeEventListener("abort",D)}};s(()=>{i()&&(h?.abort("triggered"),x(m))});const O=R=>{typeof R=="function"?(m=Promise.try(R),x(m)):d(R)};return u.error=l,u.status=g,u.refetch=()=>{h?.abort("refetch"),x(m)},[u,O]},computed:s,onCleanup:r,context:t,ref:()=>{const c=[];return(...u)=>{if(u.length===2){c.length=0;const[d,l]=u;let f=d.nextSibling;for(;f&&f!==l;){const g=f.nextSibling;c.push(f),f=g}return c}return u.length===1?(c.length=0,c.push(u.at(0)),c.at(0)):c.length>1?c:c.at(0)}},fromSignal:n,dispose(){t.length=0}}},ht=(t,e)=>{const n=new WeakMap,r=s=>{let o=!1,a=!0;const[c,i]=e.create(s.assignedNodes()),u=()=>{if(!o){if(a){a=!1;return}o=!0,i(s.assignedNodes()),requestAnimationFrame(()=>{o=!1})}};return s.addEventListener("slotchange",u),e.onCleanup(()=>{s.removeEventListener("slotchange",u)}),c};return(s="")=>{const o=s?`slot[name='${s}']`:"slot:not([name])",a=t.querySelector(o);if(!a)return console.error("no slot with that name exists, returning empty signal"),()=>[];if(n.has(a))return n.get(a);const c=r(a);return n.set(a,c),c}},gt=(t,{mountCallbacks:e,unMountCallbacks:n,signal:r})=>({signal:r,lifecyle:{onMount:s=>{e.add(s)},onUnmount:s=>{n.add(s)}},elements:{shadowRoot:()=>t,slots:ht(t,r)}}),yt=()=>{const t=pt(),e=new Set,n=new Set;return{signal:t,mountCallbacks:e,unMountCallbacks:n,values:new Map,dispose(){t.dispose(),e.clear(),n.clear()}}},J=Symbol("render"),mt=t=>{const e=t.lastIndexOf("<"),n=t.lastIndexOf(">"),r=n===-1;return e===-1?!1:r||n<e},St=["string","number","bigint","boolean","symbol"],v=t=>St.includes(typeof t),At=t=>typeof t=="object"&&t?.key===J,Q=()=>`__${(Math.random()*1e5).toFixed()}__`,$=(t,e)=>(t.forEach((n,r)=>e.set(r,n)),e),X=Symbol("css"),Z=()=>`css-${(Math.random()*1e5).toFixed()}`,Et=t=>t.template.at(-1)===".",I=t=>typeof t=="object"&&t?.key===X,_=(t,e)=>{if(v(t))return t.toString();if(Array.isArray(t)||t instanceof Set)return Array.from(t).map(n=>_(n,e)).join(" ");if(I(t))return $(t.values,e.values),Et(e)?(e.values.set(t.name,t.template),t.name):t.template;if(typeof t=="function"){const n=Z();return e.values.set(n,t),`var(--${n}, ${t()})`}return typeof t=="function"?_(t(),e):t?t.toString():""},bt=(t,...e)=>{const n={template:t[0],values:new Map,key:X,name:Z()};return t.slice(1).forEach((r,s)=>{const o=e[s];n.template+=`${_(o,n)}${r}`}),n},Rt=t=>{const e=t.template,n=e.lastIndexOf("<");if(e.indexOf(" data-update ",n)!==-1)return;const r=e.indexOf(" ",n),s=e.slice(0,r),o=e.slice(r+1);t.template=`${s} data-update ${o}`},q=(t,e)=>{if(v(t))return t;if(I(t))return $(t.values,e.values),e.values.set(t.name,t.template),t.name;if(Array.isArray(t)||t instanceof Set)return Array.from(t).map(r=>q(r,e)).join(" ");if(t&&typeof t=="object")return(t instanceof Map?Array.from(t):Object.entries(t)).map(([s,o])=>`${s}=${q(o,e)} `).join(" ");Rt(e);const n=Q();return e.values.set(n,t),n},Ct=(t,e)=>{if(v(t))return t;if(At(t))return $(t.values,e.values),t.template;if(I(t))return $(t.values,e.values),e.values.set(t.name,t.template),`<style ${Array.from(t.values.keys()).join(" ")}>${t.template}</style>`;const n=Q();return e.values.set(n,t),`<span data-replace=${n}></span>`},tt=(t,...e)=>{const n={template:t[0],values:new Map,key:J,name:""};return t.slice(1).forEach((r,s)=>{const o=e[s],a=mt(n.template)?q(o,n):Ct(o,n);n.template+=`${a}${r}`}),n},et=t=>{try{t()}catch(e){console.warn(e)}},K=(t,e,n={})=>{class r extends HTMLElement{#t=new Map;#e=yt();#n;#r;constructor(){super(),this.attachShadow({mode:"open",serializable:!0}),Array.from(this.attributes).forEach(o=>{this.#t.set(o.name,o.value)})}connectedCallback(){this.#s(),this.#e.mountCallbacks.forEach(et),this.#c()}async disconnectedCallback(){await Promise.resolve(),this.isConnected||(this.#n?.disconnect(),this.#e.unMountCallbacks.forEach(et),this.#t.clear(),this.#e.dispose())}setProperty(o,a){o==="style"||this.#t.get(o)===a||(a==null?this.#t.delete(o):this.#t.set(o,a),this.#o())}#o(){this.#r&&cancelAnimationFrame(this.#r),this.#r=requestAnimationFrame(()=>{this.#s(),this.#r=null})}#c(){this.#n?.disconnect(),this.#n=new MutationObserver(o=>{o.forEach(a=>{this.setProperty(a.attributeName,this.getAttribute(a.attributeName))})}),this.#n.observe(this,{attributes:!0})}#s(){const{template:o,values:a}=e(Object.fromEntries(this.#t),gt(this.shadowRoot,this.#e)),c=new Range().createContextualFragment(o);this.#e.values=a;const i=F(c,{activeValue:()=>{},keyFn:N},this.#e);this.shadowRoot.replaceChildren(i)}}return customElements?.get(t)||customElements.define(t,r),(s={})=>tt`<${t} ${{...s}}></${t}>`};K.html=tt,K.css=bt,C.render=K,Object.defineProperty(C,Symbol.toStringTag,{value:"Module"})});
|
package/package.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "grundlage",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"description": "a web component base render function",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"web-components"
|
|
8
|
+
],
|
|
9
|
+
"type": "module",
|
|
10
|
+
"types": "dist/grundlage.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"main": "./dist/grundlage.umd.cjs",
|
|
15
|
+
"module": "./dist/grundlage.js",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"import": "./dist/grundlage.js",
|
|
19
|
+
"require": "./dist/grundlage.umd.cjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "vite build && tsc --noCheck"
|
|
24
|
+
}
|
|
25
|
+
}
|