@polyxd/core 0.3.0
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/LICENSE +202 -0
- package/NOTICE +190 -0
- package/README.md +43 -0
- package/dist/actionbar.d.ts +20 -0
- package/dist/actionbar.js +34 -0
- package/dist/actionbar.js.map +1 -0
- package/dist/actions.d.ts +24 -0
- package/dist/actions.js +33 -0
- package/dist/actions.js.map +1 -0
- package/dist/avatar.d.ts +13 -0
- package/dist/avatar.js +63 -0
- package/dist/avatar.js.map +1 -0
- package/dist/chart.d.ts +41 -0
- package/dist/chart.js +106 -0
- package/dist/chart.js.map +1 -0
- package/dist/choice.d.ts +35 -0
- package/dist/choice.js +32 -0
- package/dist/choice.js.map +1 -0
- package/dist/collection.d.ts +54 -0
- package/dist/collection.js +61 -0
- package/dist/collection.js.map +1 -0
- package/dist/color.d.ts +20 -0
- package/dist/color.js +105 -0
- package/dist/color.js.map +1 -0
- package/dist/comparison.d.ts +21 -0
- package/dist/comparison.js +51 -0
- package/dist/comparison.js.map +1 -0
- package/dist/data.d.ts +30 -0
- package/dist/data.js +67 -0
- package/dist/data.js.map +1 -0
- package/dist/document.d.ts +64 -0
- package/dist/document.js +18 -0
- package/dist/document.js.map +1 -0
- package/dist/files.d.ts +18 -0
- package/dist/files.js +64 -0
- package/dist/files.js.map +1 -0
- package/dist/filter.d.ts +17 -0
- package/dist/filter.js +55 -0
- package/dist/filter.js.map +1 -0
- package/dist/format.d.ts +21 -0
- package/dist/format.js +81 -0
- package/dist/format.js.map +1 -0
- package/dist/frame.d.ts +21 -0
- package/dist/frame.js +30 -0
- package/dist/frame.js.map +1 -0
- package/dist/ids.d.ts +4 -0
- package/dist/ids.js +8 -0
- package/dist/ids.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/marks.d.ts +48 -0
- package/dist/marks.js +57 -0
- package/dist/marks.js.map +1 -0
- package/dist/mask.d.ts +10 -0
- package/dist/mask.js +40 -0
- package/dist/mask.js.map +1 -0
- package/dist/options.d.ts +11 -0
- package/dist/options.js +21 -0
- package/dist/options.js.map +1 -0
- package/dist/qr.d.ts +3 -0
- package/dist/qr.js +242 -0
- package/dist/qr.js.map +1 -0
- package/dist/richtext.d.ts +17 -0
- package/dist/richtext.js +59 -0
- package/dist/richtext.js.map +1 -0
- package/dist/shortcuts.d.ts +32 -0
- package/dist/shortcuts.js +59 -0
- package/dist/shortcuts.js.map +1 -0
- package/dist/skeleton.d.ts +22 -0
- package/dist/skeleton.js +32 -0
- package/dist/skeleton.js.map +1 -0
- package/dist/split.d.ts +53 -0
- package/dist/split.js +55 -0
- package/dist/split.js.map +1 -0
- package/dist/steps.d.ts +32 -0
- package/dist/steps.js +24 -0
- package/dist/steps.js.map +1 -0
- package/dist/surface.d.ts +52 -0
- package/dist/surface.js +64 -0
- package/dist/surface.js.map +1 -0
- package/dist/table.d.ts +34 -0
- package/dist/table.js +30 -0
- package/dist/table.js.map +1 -0
- package/dist/tree.d.ts +58 -0
- package/dist/tree.js +93 -0
- package/dist/tree.js.map +1 -0
- package/dist/views.d.ts +11 -0
- package/dist/views.js +10 -0
- package/dist/views.js.map +1 -0
- package/package.json +36 -0
package/dist/data.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/** JSON Pointer helpers and binding resolution. Every binding resolves to an absolute pointer. */
|
|
2
|
+
export const ROOT_SCOPE = { pointer: "" };
|
|
3
|
+
const decode = (s) => s.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
4
|
+
const encode = (s) => s.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
5
|
+
export const isBinding = (v) => !!v && typeof v === "object" && !Array.isArray(v) && typeof v.path === "string";
|
|
6
|
+
/** Absolute pointer for a path: absolute paths stay; relative ones join the item scope. */
|
|
7
|
+
export function absolute(path, scope) {
|
|
8
|
+
return path.startsWith("/") ? path : `${scope.pointer}/${path}`;
|
|
9
|
+
}
|
|
10
|
+
export function childPointer(pointer, key) {
|
|
11
|
+
return `${pointer}/${encode(String(key))}`;
|
|
12
|
+
}
|
|
13
|
+
export function get(data, pointer) {
|
|
14
|
+
if (pointer === "")
|
|
15
|
+
return data;
|
|
16
|
+
let cur = data;
|
|
17
|
+
for (const part of pointer.slice(1).split("/").map(decode)) {
|
|
18
|
+
if (cur === null || typeof cur !== "object")
|
|
19
|
+
return undefined;
|
|
20
|
+
cur = cur[part];
|
|
21
|
+
}
|
|
22
|
+
return cur;
|
|
23
|
+
}
|
|
24
|
+
/** Immutable set; creates intermediate objects (or arrays for numeric keys). */
|
|
25
|
+
export function set(data, pointer, value) {
|
|
26
|
+
const parts = pointer.slice(1).split("/").map(decode);
|
|
27
|
+
const write = (node, i) => {
|
|
28
|
+
const key = parts[i];
|
|
29
|
+
const copy = Array.isArray(node) ? [...node] : { ...(node ?? {}) };
|
|
30
|
+
if (i === parts.length - 1)
|
|
31
|
+
copy[key] = value;
|
|
32
|
+
else
|
|
33
|
+
copy[key] = write(node?.[key] ?? (/^\d+$/.test(parts[i + 1]) ? [] : {}), i + 1);
|
|
34
|
+
return copy;
|
|
35
|
+
};
|
|
36
|
+
return write(data, 0);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Host data as a list. A binding that a component repeats over should point at an array; when the
|
|
40
|
+
* host (or a generated document) points it somewhere else, the component shows nothing instead of
|
|
41
|
+
* throwing. The validator reports the mismatch.
|
|
42
|
+
*/
|
|
43
|
+
export const asList = (value) => (Array.isArray(value) ? value : []);
|
|
44
|
+
/** Resolves a literal-or-binding value. */
|
|
45
|
+
export function resolve(value, data, scope) {
|
|
46
|
+
return (isBinding(value) ? get(data, absolute(value.path, scope)) : value);
|
|
47
|
+
}
|
|
48
|
+
/** Resolves every value in an action context. */
|
|
49
|
+
export function resolveContext(context, data, scope) {
|
|
50
|
+
return Object.fromEntries(Object.entries(context ?? {}).map(([k, v]) => [k, resolve(v, data, scope)]));
|
|
51
|
+
}
|
|
52
|
+
/** A value with bindings resolved wherever they sit in it (a Custom's props). */
|
|
53
|
+
export function resolveDeep(value, data, scope) {
|
|
54
|
+
if (isBinding(value))
|
|
55
|
+
return resolve(value, data, scope);
|
|
56
|
+
if (Array.isArray(value))
|
|
57
|
+
return value.map((v) => resolveDeep(v, data, scope));
|
|
58
|
+
if (value && typeof value === "object")
|
|
59
|
+
return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, resolveDeep(v, data, scope)]));
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
/** The scopes of a list binding's items, in order: what a repeated template renders in. */
|
|
63
|
+
export function itemScopes(data, path, scope) {
|
|
64
|
+
const pointer = absolute(path, scope);
|
|
65
|
+
return asList(get(data, pointer)).map((_, i) => ({ pointer: childPointer(pointer, i) }));
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=data.js.map
|
package/dist/data.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** The document a renderer walks, and what it sends back to the host. Framework-free. */
|
|
2
|
+
export type Node = Record<string, any> & {
|
|
3
|
+
id: string;
|
|
4
|
+
component: string;
|
|
5
|
+
};
|
|
6
|
+
/** A capability the document may trigger: `{ event: { name, context } }`. */
|
|
7
|
+
export interface Action {
|
|
8
|
+
event: {
|
|
9
|
+
name: string;
|
|
10
|
+
context?: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export interface UIDocument {
|
|
14
|
+
specVersion: string;
|
|
15
|
+
surface: {
|
|
16
|
+
id: string;
|
|
17
|
+
title: string;
|
|
18
|
+
intent?: string;
|
|
19
|
+
pattern?: string;
|
|
20
|
+
journey?: string;
|
|
21
|
+
dismissible?: boolean;
|
|
22
|
+
subtitle?: unknown;
|
|
23
|
+
breadcrumbs?: {
|
|
24
|
+
label: unknown;
|
|
25
|
+
action?: any;
|
|
26
|
+
}[];
|
|
27
|
+
badge?: {
|
|
28
|
+
text: unknown;
|
|
29
|
+
tone?: string;
|
|
30
|
+
};
|
|
31
|
+
avatar?: unknown;
|
|
32
|
+
/** ActionBar id: what you can do to this record */
|
|
33
|
+
actions?: string;
|
|
34
|
+
presentation?: "page" | "panel";
|
|
35
|
+
origin?: "generated" | "authored";
|
|
36
|
+
/** A shell is the product's frame (a Frame with an Outlet); a surface is a screen inside one. */
|
|
37
|
+
kind?: "surface" | "shell";
|
|
38
|
+
};
|
|
39
|
+
root: string;
|
|
40
|
+
components: Node[];
|
|
41
|
+
data?: Record<string, unknown>;
|
|
42
|
+
}
|
|
43
|
+
export interface ActionEvent {
|
|
44
|
+
/** Capability name, e.g. "transfer.confirm" */
|
|
45
|
+
name: string;
|
|
46
|
+
/** Resolved context values */
|
|
47
|
+
context: Record<string, unknown>;
|
|
48
|
+
/** Id of the component that triggered it */
|
|
49
|
+
source: string;
|
|
50
|
+
}
|
|
51
|
+
export type NavigationPlacement = "side" | "rail" | "bar" | "drawer";
|
|
52
|
+
/** What a Frame decided for the width it has, so a host's own screens can adapt with it. */
|
|
53
|
+
export interface FrameLayout {
|
|
54
|
+
navigation: NavigationPlacement;
|
|
55
|
+
compact: boolean;
|
|
56
|
+
}
|
|
57
|
+
/** Actions the renderer handles itself; every other name reaches the host. */
|
|
58
|
+
export declare const RENDERER_ACTIONS: readonly ["ui.dismiss", "ui.back", "ui.next", "ui.copy"];
|
|
59
|
+
/** Every component the spec defines, in the registry's order: the shell's five come last. */
|
|
60
|
+
export declare const COMPONENTS: readonly ["Section", "Group", "Card", "Disclosure", "Views", "Navigation", "Text", "Metric", "DetailList", "Collection", "Table", "Chart", "Media", "Status", "TextInput", "Choice", "Toggle", "DateInput", "RangeInput", "Form", "Action", "ActionBar", "Steps", "Confirm", "Comparison", "FilterPanel", "Tag", "Identity", "Progress", "Rating", "Code", "Tree", "ActionMenu", "Panel", "FileInput", "ColorInput", "CodeInput", "Columns", "Split", "Frame", "AppBar", "Footer", "Outlet", "Custom"];
|
|
61
|
+
/** Index of a document's components by id. */
|
|
62
|
+
export declare const indexById: (doc: UIDocument) => Map<string, Node>;
|
|
63
|
+
/** A surface's main navigation, which sits outside the root and renders beside the page (a shell's is inside its Frame). */
|
|
64
|
+
export declare const mainNavigation: (doc: UIDocument) => Node | undefined;
|
package/dist/document.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** The document a renderer walks, and what it sends back to the host. Framework-free. */
|
|
2
|
+
/** Actions the renderer handles itself; every other name reaches the host. */
|
|
3
|
+
export const RENDERER_ACTIONS = ["ui.dismiss", "ui.back", "ui.next", "ui.copy"];
|
|
4
|
+
/** Every component the spec defines, in the registry's order: the shell's five come last. */
|
|
5
|
+
export const COMPONENTS = [
|
|
6
|
+
"Section", "Group", "Card", "Disclosure", "Views", "Navigation",
|
|
7
|
+
"Text", "Metric", "DetailList", "Collection", "Table", "Chart", "Media", "Status",
|
|
8
|
+
"TextInput", "Choice", "Toggle", "DateInput", "RangeInput", "Form",
|
|
9
|
+
"Action", "ActionBar", "Steps", "Confirm", "Comparison", "FilterPanel",
|
|
10
|
+
"Tag", "Identity", "Progress", "Rating", "Code", "Tree", "ActionMenu", "Panel", "FileInput", "ColorInput", "CodeInput",
|
|
11
|
+
"Columns", "Split",
|
|
12
|
+
"Frame", "AppBar", "Footer", "Outlet", "Custom",
|
|
13
|
+
];
|
|
14
|
+
/** Index of a document's components by id. */
|
|
15
|
+
export const indexById = (doc) => new Map(doc.components.map((c) => [c.id, c]));
|
|
16
|
+
/** A surface's main navigation, which sits outside the root and renders beside the page (a shell's is inside its Frame). */
|
|
17
|
+
export const mainNavigation = (doc) => doc.surface.kind === "shell" ? undefined : doc.components.find((c) => c.component === "Navigation" && (!c.kind || c.kind === "main"));
|
|
18
|
+
//# sourceMappingURL=document.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"document.js","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAAA,yFAAyF;AAmDzF,8EAA8E;AAC9E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAU,CAAC;AAEzF,6FAA6F;AAC7F,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY;IAC/D,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ;IACjF,WAAW,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM;IAClE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa;IACtE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW;IACtH,SAAS,EAAE,OAAO;IAClB,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ;CACvC,CAAC;AAEX,8CAA8C;AAC9C,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAe,EAAqB,EAAE,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AAE/G,4HAA4H;AAC5H,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,GAAe,EAAoB,EAAE,CAClE,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,YAAY,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC"}
|
package/dist/files.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** What a FileInput says about its limits, and whether a file meets them. */
|
|
2
|
+
/** 1.5 MB in binary units, as the file chooser and the OS say it. */
|
|
3
|
+
export declare function formatBytes(n: number, locale: string): string;
|
|
4
|
+
/** '.pdf' → 'PDF', 'image/*' → 'images', 'application/zip' → 'ZIP'. */
|
|
5
|
+
export declare function describeType(a: string): string;
|
|
6
|
+
export declare function listText(items: string[]): string;
|
|
7
|
+
export declare function matchesAccept(file: {
|
|
8
|
+
name: string;
|
|
9
|
+
type: string;
|
|
10
|
+
}, accept: string[]): boolean;
|
|
11
|
+
/** The limits, said before choosing: "Accepts PDF or images. Up to 5 MB each." */
|
|
12
|
+
export declare function fileLimits(accept: string[], maxSize: number | undefined, multiple: boolean, locale: string): string;
|
|
13
|
+
/** Why a file was refused, or nothing when it is fine. */
|
|
14
|
+
export declare function refuseFile(file: {
|
|
15
|
+
name: string;
|
|
16
|
+
size: number;
|
|
17
|
+
type: string;
|
|
18
|
+
}, accept: string[], maxSize: number | undefined, locale: string): string | undefined;
|
package/dist/files.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** What a FileInput says about its limits, and whether a file meets them. */
|
|
2
|
+
const UNITS = ["byte", "kilobyte", "megabyte", "gigabyte"];
|
|
3
|
+
/** 1.5 MB in binary units, as the file chooser and the OS say it. */
|
|
4
|
+
export function formatBytes(n, locale) {
|
|
5
|
+
let i = 0;
|
|
6
|
+
let v = n;
|
|
7
|
+
while (v >= 1024 && i < UNITS.length - 1) {
|
|
8
|
+
v /= 1024;
|
|
9
|
+
i++;
|
|
10
|
+
}
|
|
11
|
+
try {
|
|
12
|
+
return new Intl.NumberFormat(locale, { style: "unit", unit: UNITS[i], unitDisplay: "short", maximumFractionDigits: v < 10 ? 1 : 0 }).format(v);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return `${Math.round(v * 10) / 10} ${["B", "KB", "MB", "GB"][i]}`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** '.pdf' → 'PDF', 'image/*' → 'images', 'application/zip' → 'ZIP'. */
|
|
19
|
+
export function describeType(a) {
|
|
20
|
+
const t = a.trim().toLowerCase();
|
|
21
|
+
if (t.startsWith("."))
|
|
22
|
+
return t.slice(1).toUpperCase();
|
|
23
|
+
const wild = { "image/*": "images", "video/*": "videos", "audio/*": "audio", "text/*": "text files" };
|
|
24
|
+
if (wild[t])
|
|
25
|
+
return wild[t];
|
|
26
|
+
if (t === "application/pdf")
|
|
27
|
+
return "PDF";
|
|
28
|
+
const sub = t.split("/")[1];
|
|
29
|
+
return sub ? sub.replace(/^(x-|vnd\.)/, "").toUpperCase() : a;
|
|
30
|
+
}
|
|
31
|
+
export function listText(items) {
|
|
32
|
+
if (items.length <= 1)
|
|
33
|
+
return items.join("");
|
|
34
|
+
return `${items.slice(0, -1).join(", ")} or ${items[items.length - 1]}`;
|
|
35
|
+
}
|
|
36
|
+
export function matchesAccept(file, accept) {
|
|
37
|
+
if (accept.length === 0)
|
|
38
|
+
return true;
|
|
39
|
+
const name = file.name.toLowerCase();
|
|
40
|
+
const type = file.type.toLowerCase();
|
|
41
|
+
return accept.some((a) => {
|
|
42
|
+
const t = a.trim().toLowerCase();
|
|
43
|
+
if (t.startsWith("."))
|
|
44
|
+
return name.endsWith(t);
|
|
45
|
+
if (t.endsWith("/*"))
|
|
46
|
+
return type.startsWith(t.slice(0, -1));
|
|
47
|
+
return type === t;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/** The limits, said before choosing: "Accepts PDF or images. Up to 5 MB each." */
|
|
51
|
+
export function fileLimits(accept, maxSize, multiple, locale) {
|
|
52
|
+
const acceptText = accept.length ? listText(accept.map(describeType)) : "";
|
|
53
|
+
return [acceptText && `Accepts ${acceptText}.`, maxSize && `Up to ${formatBytes(maxSize, locale)}${multiple ? " each" : ""}.`].filter(Boolean).join(" ");
|
|
54
|
+
}
|
|
55
|
+
/** Why a file was refused, or nothing when it is fine. */
|
|
56
|
+
export function refuseFile(file, accept, maxSize, locale) {
|
|
57
|
+
if (maxSize && file.size > maxSize)
|
|
58
|
+
return `${file.name} is ${formatBytes(file.size, locale)}; the limit is ${formatBytes(maxSize, locale)}.`;
|
|
59
|
+
const acceptText = accept.length ? listText(accept.map(describeType)) : "";
|
|
60
|
+
if (!matchesAccept(file, accept))
|
|
61
|
+
return `${file.name} isn't an accepted type${acceptText ? ` (${acceptText})` : ""}.`;
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"files.js","sourceRoot":"","sources":["../src/files.ts"],"names":[],"mappings":"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"}
|
package/dist/filter.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** What each filter input currently narrows by, and what removing it writes. */
|
|
2
|
+
import { type Scope } from "./data.ts";
|
|
3
|
+
import type { Node } from "./document.ts";
|
|
4
|
+
export interface ActiveFilter {
|
|
5
|
+
key: string;
|
|
6
|
+
label: string;
|
|
7
|
+
/** The binding to write, and what to write to clear this filter */
|
|
8
|
+
binding: {
|
|
9
|
+
path: string;
|
|
10
|
+
};
|
|
11
|
+
cleared: unknown;
|
|
12
|
+
}
|
|
13
|
+
export declare function activeFilters(filters: Node[], data: unknown, scope: Scope, locale: string, text: (v: unknown) => string): ActiveFilter[];
|
|
14
|
+
/** Below this width the filters move into a bottom sheet. */
|
|
15
|
+
export declare const FILTER_COMPACT_PX = 640;
|
|
16
|
+
/** "12 results", "1 result". */
|
|
17
|
+
export declare const resultCountText: (count: number | undefined, locale: string) => string | undefined;
|
package/dist/filter.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/** What each filter input currently narrows by, and what removing it writes. */
|
|
2
|
+
import { isBinding, resolve } from "./data.js";
|
|
3
|
+
import { formatValue, resolveFormat } from "./format.js";
|
|
4
|
+
import { optionsOf } from "./options.js";
|
|
5
|
+
export function activeFilters(filters, data, scope, locale, text) {
|
|
6
|
+
const out = [];
|
|
7
|
+
for (const c of filters) {
|
|
8
|
+
if (!isBinding(c.value))
|
|
9
|
+
continue;
|
|
10
|
+
const binding = c.value;
|
|
11
|
+
const v = resolve(c.value, data, scope);
|
|
12
|
+
const name = text(c.label);
|
|
13
|
+
const fmt = (n) => formatValue(n, resolveFormat(c.format ?? { type: "number" }, data, scope), locale);
|
|
14
|
+
switch (c.component) {
|
|
15
|
+
case "Choice": {
|
|
16
|
+
const options = optionsOf(c, data, scope, text);
|
|
17
|
+
const labelOf = (x) => options.find((o) => o.value === x)?.label ?? String(x);
|
|
18
|
+
if (Array.isArray(v))
|
|
19
|
+
for (const x of v)
|
|
20
|
+
out.push({ key: `${c.id}:${x}`, label: labelOf(x), binding, cleared: v.filter((y) => y !== x) });
|
|
21
|
+
else if (v !== null && v !== undefined && v !== "")
|
|
22
|
+
out.push({ key: c.id, label: labelOf(v), binding, cleared: null });
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
case "RangeInput": {
|
|
26
|
+
if (c.mode === "range" && Array.isArray(v)) {
|
|
27
|
+
const [lo, hi] = v.map(Number);
|
|
28
|
+
if (lo > c.min || hi < c.max)
|
|
29
|
+
out.push({ key: c.id, label: `${name}: ${fmt(lo)} – ${fmt(hi)}`, binding, cleared: [c.min, c.max] });
|
|
30
|
+
}
|
|
31
|
+
else if (typeof v === "number" && v < c.max)
|
|
32
|
+
out.push({ key: c.id, label: `${name}: ${fmt(v)}`, binding, cleared: c.max });
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
case "Toggle":
|
|
36
|
+
if (v === true)
|
|
37
|
+
out.push({ key: c.id, label: name, binding, cleared: false });
|
|
38
|
+
break;
|
|
39
|
+
case "TextInput":
|
|
40
|
+
if (typeof v === "string" && v.trim())
|
|
41
|
+
out.push({ key: c.id, label: `${name}: ${v}`, binding, cleared: "" });
|
|
42
|
+
break;
|
|
43
|
+
case "DateInput":
|
|
44
|
+
if (v)
|
|
45
|
+
out.push({ key: c.id, label: `${name}: ${String(v)}`, binding, cleared: null });
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return out;
|
|
50
|
+
}
|
|
51
|
+
/** Below this width the filters move into a bottom sheet. */
|
|
52
|
+
export const FILTER_COMPACT_PX = 640;
|
|
53
|
+
/** "12 results", "1 result". */
|
|
54
|
+
export const resultCountText = (count, locale) => (count === undefined ? undefined : `${formatValue(count, { type: "number" }, locale)} ${count === 1 ? "result" : "results"}`);
|
|
55
|
+
//# sourceMappingURL=filter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../src/filter.ts"],"names":[],"mappings":"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"}
|
package/dist/format.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Localised presentation of values. The model never pre-formats; the renderer does it here. */
|
|
2
|
+
import { type Scope } from "./data.ts";
|
|
3
|
+
export interface Format {
|
|
4
|
+
type: "text" | "number" | "currency" | "percent" | "date" | "time" | "datetime" | "relativeTime" | "duration" | "color" | "bytes";
|
|
5
|
+
/** ISO 4217 code, or a binding to one (resolved by the renderer before formatting) */
|
|
6
|
+
currency?: string | {
|
|
7
|
+
path: string;
|
|
8
|
+
};
|
|
9
|
+
precision?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function formatValue(value: unknown, format: Format | undefined, locale: string, now?: number): string;
|
|
12
|
+
/** A CSS colour a swatch can safely take as its background: named, hex, rgb()/hsl()/oklch() etc. Anything else is not painted. */
|
|
13
|
+
export declare function safeColor(value: unknown): string | undefined;
|
|
14
|
+
/** Currency symbol for input adornments, e.g. "£". */
|
|
15
|
+
export declare function currencySymbol(currency: string, locale: string): string;
|
|
16
|
+
/** A format's currency may itself be bound to data (e.g. the account's currency). */
|
|
17
|
+
export declare function resolveFormat(format: Format | undefined, data: unknown, scope: Scope): Format | undefined;
|
|
18
|
+
/** A count as people read it, in the locale: 1,204. */
|
|
19
|
+
export declare const formatCount: (n: number, locale: string) => string;
|
|
20
|
+
/** A whole percentage: 0.42 → "42%". */
|
|
21
|
+
export declare const formatPercent: (fraction: number, locale: string) => string;
|
package/dist/format.js
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** Localised presentation of values. The model never pre-formats; the renderer does it here. */
|
|
2
|
+
import { resolve } from "./data.js";
|
|
3
|
+
export function formatValue(value, format, locale, now = Date.now()) {
|
|
4
|
+
if (value === null || value === undefined || value === "")
|
|
5
|
+
return "—";
|
|
6
|
+
if (!format || format.type === "text")
|
|
7
|
+
return Array.isArray(value) ? value.join(", ") : String(value);
|
|
8
|
+
const n = typeof value === "number" ? value : Number(value);
|
|
9
|
+
const digits = format.precision === undefined ? {} : { minimumFractionDigits: format.precision, maximumFractionDigits: format.precision };
|
|
10
|
+
try {
|
|
11
|
+
switch (format.type) {
|
|
12
|
+
case "number":
|
|
13
|
+
return new Intl.NumberFormat(locale, digits).format(n);
|
|
14
|
+
case "currency":
|
|
15
|
+
return new Intl.NumberFormat(locale, { style: "currency", currency: typeof format.currency === "string" ? format.currency : "USD", ...digits }).format(n);
|
|
16
|
+
case "percent":
|
|
17
|
+
return new Intl.NumberFormat(locale, { style: "percent", maximumFractionDigits: format.precision ?? 1 }).format(n);
|
|
18
|
+
case "date":
|
|
19
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: "medium", timeZone: "UTC" }).format(new Date(String(value)));
|
|
20
|
+
case "time":
|
|
21
|
+
return new Intl.DateTimeFormat(locale, { timeStyle: "short", timeZone: "UTC" }).format(new Date(String(value)));
|
|
22
|
+
case "datetime":
|
|
23
|
+
return new Intl.DateTimeFormat(locale, { dateStyle: "medium", timeStyle: "short", timeZone: "UTC" }).format(new Date(String(value)));
|
|
24
|
+
case "relativeTime": {
|
|
25
|
+
const diff = (new Date(String(value)).getTime() - now) / 1000;
|
|
26
|
+
const units = [["year", 31536000], ["month", 2592000], ["day", 86400], ["hour", 3600], ["minute", 60]];
|
|
27
|
+
const rtf = new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
|
|
28
|
+
for (const [unit, secs] of units)
|
|
29
|
+
if (Math.abs(diff) >= secs)
|
|
30
|
+
return rtf.format(Math.round(diff / secs), unit);
|
|
31
|
+
return rtf.format(Math.round(diff), "second");
|
|
32
|
+
}
|
|
33
|
+
case "duration": {
|
|
34
|
+
const mins = Math.round(n / 60);
|
|
35
|
+
return mins >= 60 ? `${Math.floor(mins / 60)} h ${mins % 60} min` : `${mins} min`;
|
|
36
|
+
}
|
|
37
|
+
case "color":
|
|
38
|
+
// The value is the colour itself; renderers show a swatch of it beside this text.
|
|
39
|
+
return String(value).trim();
|
|
40
|
+
case "bytes": {
|
|
41
|
+
// 1.2 MB: decimal units, one decimal past kilobytes.
|
|
42
|
+
const units = ["byte", "kilobyte", "megabyte", "gigabyte", "terabyte"];
|
|
43
|
+
let i = 0;
|
|
44
|
+
let v = Math.abs(n);
|
|
45
|
+
while (v >= 1000 && i < units.length - 1)
|
|
46
|
+
(v /= 1000), i++;
|
|
47
|
+
if (i === 0)
|
|
48
|
+
return `${new Intl.NumberFormat(locale, { maximumFractionDigits: 0 }).format(n)} B`;
|
|
49
|
+
return new Intl.NumberFormat(locale, { style: "unit", unit: units[i], unitDisplay: "short", maximumFractionDigits: format.precision ?? 1 }).format(n < 0 ? -v : v);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return String(value);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/** A CSS colour a swatch can safely take as its background: named, hex, rgb()/hsl()/oklch() etc. Anything else is not painted. */
|
|
58
|
+
export function safeColor(value) {
|
|
59
|
+
const v = String(value ?? "").trim();
|
|
60
|
+
return /^(#[0-9a-f]{3,8}|[a-z]{3,20}|(rgb|rgba|hsl|hsla|oklch|oklab|lab|lch|hwb)\([\d.,%\s\/-]+\))$/i.test(v) ? v : undefined;
|
|
61
|
+
}
|
|
62
|
+
/** Currency symbol for input adornments, e.g. "£". */
|
|
63
|
+
export function currencySymbol(currency, locale) {
|
|
64
|
+
try {
|
|
65
|
+
return new Intl.NumberFormat(locale, { style: "currency", currency }).formatToParts(0).find((p) => p.type === "currency")?.value ?? currency;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return currency;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/** A format's currency may itself be bound to data (e.g. the account's currency). */
|
|
72
|
+
export function resolveFormat(format, data, scope) {
|
|
73
|
+
if (!format?.currency || typeof format.currency === "string")
|
|
74
|
+
return format;
|
|
75
|
+
return { ...format, currency: resolve(format.currency, data, scope) };
|
|
76
|
+
}
|
|
77
|
+
/** A count as people read it, in the locale: 1,204. */
|
|
78
|
+
export const formatCount = (n, locale) => new Intl.NumberFormat(locale).format(n);
|
|
79
|
+
/** A whole percentage: 0.42 → "42%". */
|
|
80
|
+
export const formatPercent = (fraction, locale) => new Intl.NumberFormat(locale, { style: "percent", maximumFractionDigits: 0 }).format(fraction);
|
|
81
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../src/format.ts"],"names":[],"mappings":"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"}
|
package/dist/frame.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** The Frame's layout rule, per width and placement, and the navigation's own breakpoint. */
|
|
2
|
+
import type { NavigationPlacement } from "./document.ts";
|
|
3
|
+
/** The Frame's breakpoints, on its own width: wide has room for a side column, medium for a rail. */
|
|
4
|
+
export declare const WIDE_PX = 1024;
|
|
5
|
+
export declare const MEDIUM_PX = 640;
|
|
6
|
+
/** A bottom bar holds at most this many items; more go behind a menu button. */
|
|
7
|
+
export declare const BAR_MAX = 5;
|
|
8
|
+
/** Below this width a surface's own navigation moves behind a menu button. */
|
|
9
|
+
export declare const NAV_COMPACT_PX = 900;
|
|
10
|
+
export type FrameWidth = "wide" | "medium" | "compact";
|
|
11
|
+
export declare const frameWidth: (px: number) => FrameWidth;
|
|
12
|
+
/**
|
|
13
|
+
* Where the main navigation goes. 'auto' follows the width. 'side' and 'rail' hold on wide and
|
|
14
|
+
* medium layouts and still collapse on compact, where neither fits beside a screen; 'bar' and
|
|
15
|
+
* 'drawer' hold everywhere, except that a bar with too many items becomes a drawer.
|
|
16
|
+
*/
|
|
17
|
+
export declare function placementFor(placement: string | undefined, width: FrameWidth, items: number): NavigationPlacement;
|
|
18
|
+
/** The AppBar's title: the current screen's on compact layouts when the frame knows it, else the product's. */
|
|
19
|
+
export declare const appBarTitle: (product: string, compact: boolean, current?: string) => string;
|
|
20
|
+
/** The document title follows the current screen: "Payments · Halden". */
|
|
21
|
+
export declare const documentTitle: (product: string, current?: string) => string;
|
package/dist/frame.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** The Frame's breakpoints, on its own width: wide has room for a side column, medium for a rail. */
|
|
2
|
+
export const WIDE_PX = 1024;
|
|
3
|
+
export const MEDIUM_PX = 640;
|
|
4
|
+
/** A bottom bar holds at most this many items; more go behind a menu button. */
|
|
5
|
+
export const BAR_MAX = 5;
|
|
6
|
+
/** Below this width a surface's own navigation moves behind a menu button. */
|
|
7
|
+
export const NAV_COMPACT_PX = 900;
|
|
8
|
+
export const frameWidth = (px) => (px >= WIDE_PX ? "wide" : px >= MEDIUM_PX ? "medium" : "compact");
|
|
9
|
+
/**
|
|
10
|
+
* Where the main navigation goes. 'auto' follows the width. 'side' and 'rail' hold on wide and
|
|
11
|
+
* medium layouts and still collapse on compact, where neither fits beside a screen; 'bar' and
|
|
12
|
+
* 'drawer' hold everywhere, except that a bar with too many items becomes a drawer.
|
|
13
|
+
*/
|
|
14
|
+
export function placementFor(placement, width, items) {
|
|
15
|
+
const fits = items <= BAR_MAX;
|
|
16
|
+
if (placement === "bar")
|
|
17
|
+
return fits ? "bar" : "drawer";
|
|
18
|
+
if (placement === "drawer")
|
|
19
|
+
return "drawer";
|
|
20
|
+
if (width === "compact")
|
|
21
|
+
return fits ? "bar" : "drawer";
|
|
22
|
+
if (placement === "side" || placement === "rail")
|
|
23
|
+
return placement;
|
|
24
|
+
return width === "wide" ? "side" : "rail";
|
|
25
|
+
}
|
|
26
|
+
/** The AppBar's title: the current screen's on compact layouts when the frame knows it, else the product's. */
|
|
27
|
+
export const appBarTitle = (product, compact, current) => (compact && current ? current : product);
|
|
28
|
+
/** The document title follows the current screen: "Payments · Halden". */
|
|
29
|
+
export const documentTitle = (product, current) => (current ? `${current} · ${product}` : product);
|
|
30
|
+
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../src/frame.ts"],"names":[],"mappings":"AAGA,qGAAqG;AACrG,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC;AAC5B,MAAM,CAAC,MAAM,SAAS,GAAG,GAAG,CAAC;AAC7B,gFAAgF;AAChF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,CAAC;AACzB,8EAA8E;AAC9E,MAAM,CAAC,MAAM,cAAc,GAAG,GAAG,CAAC;AAIlC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAU,EAAc,EAAE,CAAC,CAAC,EAAE,IAAI,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;AAExH;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,SAA6B,EAAE,KAAiB,EAAE,KAAa;IAC1F,MAAM,IAAI,GAAG,KAAK,IAAI,OAAO,CAAC;IAC9B,IAAI,SAAS,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;IACxD,IAAI,SAAS,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC5C,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;IACxD,IAAI,SAAS,KAAK,MAAM,IAAI,SAAS,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IACnE,OAAO,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAC5C,CAAC;AAED,+GAA+G;AAC/G,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAe,EAAE,OAAgB,EAAE,OAAgB,EAAU,EAAE,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAErI,0EAA0E;AAC1E,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAe,EAAE,OAAgB,EAAU,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,MAAM,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC"}
|
package/dist/ids.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Element ids from values: JSON is exact but not id-safe ("p_tom" has quotes), so it is encoded. */
|
|
2
|
+
export declare const idOf: (prefix: string, value: unknown) => string;
|
|
3
|
+
/** A generator of ids unique within one surface, for label/control pairs and live regions. */
|
|
4
|
+
export declare function idGenerator(prefix?: string): () => string;
|
package/dist/ids.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Element ids from values: JSON is exact but not id-safe ("p_tom" has quotes), so it is encoded. */
|
|
2
|
+
export const idOf = (prefix, value) => `${prefix}-${encodeURIComponent(JSON.stringify(value)).replace(/%/g, "_")}`;
|
|
3
|
+
/** A generator of ids unique within one surface, for label/control pairs and live regions. */
|
|
4
|
+
export function idGenerator(prefix = "pxd") {
|
|
5
|
+
let n = 0;
|
|
6
|
+
return () => `${prefix}-${(n++).toString(36)}`;
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=ids.js.map
|
package/dist/ids.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ids.js","sourceRoot":"","sources":["../src/ids.ts"],"names":[],"mappings":"AAAA,qGAAqG;AACrG,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,MAAc,EAAE,KAAc,EAAU,EAAE,CAAC,GAAG,MAAM,IAAI,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;AAE5I,8FAA8F;AAC9F,MAAM,UAAU,WAAW,CAAC,MAAM,GAAG,KAAK;IACxC,IAAI,CAAC,GAAG,CAAC,CAAC;IACV,OAAO,GAAG,EAAE,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;AACjD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export { type Node, type UIDocument, type Action, type ActionEvent, type NavigationPlacement, type FrameLayout, RENDERER_ACTIONS, COMPONENTS, indexById, mainNavigation } from "./document.ts";
|
|
2
|
+
export { type Data, type Scope, ROOT_SCOPE, isBinding, absolute, childPointer, get, set, asList, resolve, resolveContext, resolveDeep, itemScopes } from "./data.ts";
|
|
3
|
+
export { type Format, formatValue, safeColor, currencySymbol, resolveFormat, formatCount, formatPercent } from "./format.ts";
|
|
4
|
+
export { type Option, optionsOf } from "./options.ts";
|
|
5
|
+
export { type ChoiceControl, type ChoicePlan, CHIPS_MAX, CHIP_LABEL_MAX, SEARCHABLE_PAST, planChoice, optionKey, matchesQuery, partitionRecent, toggleSelection, isSelected, searchPlaceholder } from "./choice.ts";
|
|
6
|
+
export { idOf, idGenerator } from "./ids.ts";
|
|
7
|
+
export { type StepsState, type StepsAction, stepsReducer, initialStep, isLastStep, stepsProgress, TASK_STATUS, taskStatus, tasklistReducer, tasklistProgress } from "./steps.ts";
|
|
8
|
+
export { type View, selectedView, viewsReducer } from "./views.ts";
|
|
9
|
+
export { type SplitState, type SplitAction, type SplitSelection, SPLIT_COMPACT_PX, SHARE, SHARE_MIN, SHARE_MAX, initialSplit, clampShare, splitReducer, splitPanes, splitItemValue, splitSelection } from "./split.ts";
|
|
10
|
+
export { type SkeletonShape, type SkeletonPart, type BlockKind, type BlockSize, PATTERN_SHAPE, SKELETON_SHAPES, SKELETON_GROUP_CLASS, skeletonShape, skeletonStatus } from "./skeleton.ts";
|
|
11
|
+
export { type PagingState, TABLE_COMPACT_PX, PAGE_SIZES, isNumericColumn, stackedColumns, rowValue, rowScopes, toggleValue, nextSort, columnCount, paging } from "./table.ts";
|
|
12
|
+
export { type DispatchHandlers, isRendererAction, dispatchAction, contextWithValue, copyText, rowChangeAction } from "./actions.ts";
|
|
13
|
+
export { type Shortcut, type KeyLike, type ModifierFlag, SHORTCUT_KEYS, MODIFIER_FLAGS, parseShortcut, shortcutMatches, unmodified, isApplePlatform } from "./shortcuts.ts";
|
|
14
|
+
export { type FrameWidth, WIDE_PX, MEDIUM_PX, BAR_MAX, NAV_COMPACT_PX, frameWidth, placementFor, appBarTitle, documentTitle } from "./frame.ts";
|
|
15
|
+
export { type RichToken, richText } from "./richtext.ts";
|
|
16
|
+
export { applyMask, maskIsNumeric, numericValue, storedText, addTag } from "./mask.ts";
|
|
17
|
+
export { type ColorFormat, type RGBA, clamp, hslToRgb, rgbToHsl, parseColor, formatColor, toHex6, sameColor, colorPlaceholder } from "./color.ts";
|
|
18
|
+
export { formatBytes, describeType, listText, matchesAccept, fileLimits, refuseFile } from "./files.ts";
|
|
19
|
+
export { type MetricChange, type GaugeState, metricChange, meterHint, gaugeState, starsLabel, ratingSaid, maskSecret, IDENTITY_SIZE, groupSummary } from "./marks.ts";
|
|
20
|
+
export { avatarTone, initialsOf, isMediaRef, ICON_PATHS, iconPath, STATUS_ICON, STAR_PATH } from "./avatar.ts";
|
|
21
|
+
export { type CalendarMonth, collectionItemValue, collectionLayout, orderedIndices, moveItem, dateParts, monthToShow, shiftMonth, calendarMonth, nearestSlide } from "./collection.ts";
|
|
22
|
+
export { bestPerAttribute, groupAttributes, recommendedFirst, groupItems, navigationLabel } from "./comparison.ts";
|
|
23
|
+
export { type Rect, CHART_W, CHART_H, CHART_PAD, MARKERS, seriesColor, niceMax, axisLabel, treemap, verticalScale, markerShape, flowLayout } from "./chart.ts";
|
|
24
|
+
export { type TreeRow, type TreeMove, VIRTUAL_LIMIT, OVERSCAN, TYPEAHEAD_MS, treeRows, typeAheadTarget, treeKey, visibleWindow } from "./tree.ts";
|
|
25
|
+
export { type ActiveFilter, FILTER_COMPACT_PX, activeFilters, resultCountText } from "./filter.ts";
|
|
26
|
+
export { qrEncode } from "./qr.ts";
|
|
27
|
+
export { MORE_ACTIONS, TRIGGER_FALLBACK, minShown, fitActions, menuOrder } from "./actionbar.ts";
|
|
28
|
+
export { type Surface, type SurfaceOptions, createSurface, a11yAttributes } from "./surface.ts";
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export { RENDERER_ACTIONS, COMPONENTS, indexById, mainNavigation } from "./document.js";
|
|
2
|
+
export { ROOT_SCOPE, isBinding, absolute, childPointer, get, set, asList, resolve, resolveContext, resolveDeep, itemScopes } from "./data.js";
|
|
3
|
+
export { formatValue, safeColor, currencySymbol, resolveFormat, formatCount, formatPercent } from "./format.js";
|
|
4
|
+
export { optionsOf } from "./options.js";
|
|
5
|
+
export { CHIPS_MAX, CHIP_LABEL_MAX, SEARCHABLE_PAST, planChoice, optionKey, matchesQuery, partitionRecent, toggleSelection, isSelected, searchPlaceholder } from "./choice.js";
|
|
6
|
+
export { idOf, idGenerator } from "./ids.js";
|
|
7
|
+
export { stepsReducer, initialStep, isLastStep, stepsProgress, TASK_STATUS, taskStatus, tasklistReducer, tasklistProgress } from "./steps.js";
|
|
8
|
+
export { selectedView, viewsReducer } from "./views.js";
|
|
9
|
+
export { SPLIT_COMPACT_PX, SHARE, SHARE_MIN, SHARE_MAX, initialSplit, clampShare, splitReducer, splitPanes, splitItemValue, splitSelection } from "./split.js";
|
|
10
|
+
export { PATTERN_SHAPE, SKELETON_SHAPES, SKELETON_GROUP_CLASS, skeletonShape, skeletonStatus } from "./skeleton.js";
|
|
11
|
+
export { TABLE_COMPACT_PX, PAGE_SIZES, isNumericColumn, stackedColumns, rowValue, rowScopes, toggleValue, nextSort, columnCount, paging } from "./table.js";
|
|
12
|
+
export { isRendererAction, dispatchAction, contextWithValue, copyText, rowChangeAction } from "./actions.js";
|
|
13
|
+
export { SHORTCUT_KEYS, MODIFIER_FLAGS, parseShortcut, shortcutMatches, unmodified, isApplePlatform } from "./shortcuts.js";
|
|
14
|
+
export { WIDE_PX, MEDIUM_PX, BAR_MAX, NAV_COMPACT_PX, frameWidth, placementFor, appBarTitle, documentTitle } from "./frame.js";
|
|
15
|
+
export { richText } from "./richtext.js";
|
|
16
|
+
export { applyMask, maskIsNumeric, numericValue, storedText, addTag } from "./mask.js";
|
|
17
|
+
export { clamp, hslToRgb, rgbToHsl, parseColor, formatColor, toHex6, sameColor, colorPlaceholder } from "./color.js";
|
|
18
|
+
export { formatBytes, describeType, listText, matchesAccept, fileLimits, refuseFile } from "./files.js";
|
|
19
|
+
export { metricChange, meterHint, gaugeState, starsLabel, ratingSaid, maskSecret, IDENTITY_SIZE, groupSummary } from "./marks.js";
|
|
20
|
+
export { avatarTone, initialsOf, isMediaRef, ICON_PATHS, iconPath, STATUS_ICON, STAR_PATH } from "./avatar.js";
|
|
21
|
+
export { collectionItemValue, collectionLayout, orderedIndices, moveItem, dateParts, monthToShow, shiftMonth, calendarMonth, nearestSlide } from "./collection.js";
|
|
22
|
+
export { bestPerAttribute, groupAttributes, recommendedFirst, groupItems, navigationLabel } from "./comparison.js";
|
|
23
|
+
export { CHART_W, CHART_H, CHART_PAD, MARKERS, seriesColor, niceMax, axisLabel, treemap, verticalScale, markerShape, flowLayout } from "./chart.js";
|
|
24
|
+
export { VIRTUAL_LIMIT, OVERSCAN, TYPEAHEAD_MS, treeRows, typeAheadTarget, treeKey, visibleWindow } from "./tree.js";
|
|
25
|
+
export { FILTER_COMPACT_PX, activeFilters, resultCountText } from "./filter.js";
|
|
26
|
+
export { qrEncode } from "./qr.js";
|
|
27
|
+
export { MORE_ACTIONS, TRIGGER_FALLBACK, minShown, fitActions, menuOrder } from "./actionbar.js";
|
|
28
|
+
export { createSurface, a11yAttributes } from "./surface.js";
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|