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 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
+ }