@plitzi/sdk-shared 0.37.9 → 0.38.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.
Files changed (135) hide show
  1. package/CHANGELOG.md +601 -0
  2. package/dist/actions/index.d.ts +1 -1
  3. package/dist/actions/index.mjs +3 -3
  4. package/dist/actions/triggerParams.mjs +7 -6
  5. package/dist/actions/validateDocument.d.ts +3 -0
  6. package/dist/actions/validateDocument.mjs +89 -88
  7. package/dist/authoring/elementCallbacks.d.ts +65 -0
  8. package/dist/authoring/elementCallbacks.mjs +72 -8
  9. package/dist/authoring/index.mjs +3 -3
  10. package/dist/builder/contexts/BuilderContext.d.ts +18 -7
  11. package/dist/connectors/index.d.ts +1 -1
  12. package/dist/connectors/index.mjs +2 -2
  13. package/dist/connectors/validateManifest.d.ts +3 -0
  14. package/dist/connectors/validateManifest.mjs +77 -76
  15. package/dist/dataSource/computed.mjs +25 -29
  16. package/dist/dataSource/globalSources.d.ts +15 -0
  17. package/dist/dataSource/globalSources.mjs +13 -0
  18. package/dist/dataSource/index.d.ts +2 -0
  19. package/dist/dataSource/index.mjs +8 -7
  20. package/dist/devTools/utils/PlitziConsole.d.ts +9 -0
  21. package/dist/devTools/utils/PlitziConsole.mjs +27 -7
  22. package/dist/flags/flagsCookie.d.ts +26 -0
  23. package/dist/flags/flagsCookie.mjs +20 -0
  24. package/dist/flags/index.d.ts +3 -0
  25. package/dist/flags/index.mjs +4 -0
  26. package/dist/flags/resolveFlags.d.ts +60 -0
  27. package/dist/flags/resolveFlags.mjs +38 -0
  28. package/dist/flags/schemaFlag.d.ts +11 -0
  29. package/dist/flags/schemaFlag.mjs +9 -0
  30. package/dist/flags/useFlagResolution.d.ts +13 -0
  31. package/dist/flags/useFlagResolution.mjs +43 -0
  32. package/dist/helpers/eventTarget.d.ts +10 -0
  33. package/dist/helpers/eventTarget.mjs +4 -0
  34. package/dist/helpers/images.d.ts +18 -0
  35. package/dist/helpers/images.mjs +13 -0
  36. package/dist/helpers/index.d.ts +3 -0
  37. package/dist/helpers/index.mjs +21 -18
  38. package/dist/helpers/interval.d.ts +18 -0
  39. package/dist/helpers/interval.mjs +7 -0
  40. package/dist/helpers/isRecord.d.ts +2 -0
  41. package/dist/helpers/isRecord.mjs +4 -0
  42. package/dist/helpers/scroll.d.ts +42 -0
  43. package/dist/helpers/scroll.mjs +30 -0
  44. package/dist/helpers/twigWrapper/TemplateCache/TemplateCache.mjs +1 -1
  45. package/dist/helpers/twigWrapper/filters/filters.mjs +38 -2
  46. package/dist/history/describe.mjs +3 -1
  47. package/dist/history/diff.d.ts +1 -1
  48. package/dist/history/diff.mjs +1 -0
  49. package/dist/history/types.d.ts +1 -1
  50. package/dist/hooks/index.mjs +5 -5
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.mjs +90 -76
  53. package/dist/navigation/routes.mjs +6 -4
  54. package/dist/network/graphql/builder/Mutations/Space/SpaceAddSnippetMutation.d.ts +2 -0
  55. package/dist/network/graphql/builder/Mutations/Space/SpaceAddSnippetMutation.mjs +4 -0
  56. package/dist/network/graphql/builder/Mutations/Space/flags/SpacePublishFlagsMutation.d.ts +12 -0
  57. package/dist/network/graphql/builder/Mutations/Space/flags/SpacePublishFlagsMutation.mjs +4 -0
  58. package/dist/network/graphql/builder/Mutations/Space/flags/SpaceRemoveFlagMutation.d.ts +2 -0
  59. package/dist/network/graphql/builder/Mutations/Space/flags/SpaceRemoveFlagMutation.mjs +4 -0
  60. package/dist/network/graphql/builder/Mutations/Space/flags/SpaceSetFlagMutation.d.ts +3 -0
  61. package/dist/network/graphql/builder/Mutations/Space/flags/SpaceSetFlagMutation.mjs +4 -0
  62. package/dist/network/graphql/builder/Mutations/index.d.ts +5 -1
  63. package/dist/network/graphql/builder/Mutations/index.mjs +122 -116
  64. package/dist/network/graphql/builder/Queries/InitQuery.d.ts +3 -1
  65. package/dist/network/graphql/builder/Queries/InitQuery.mjs +1 -1
  66. package/dist/network/graphql/builder/Queries/Space/SpaceIssuesQuery.d.ts +16 -2
  67. package/dist/network/graphql/builder/Queries/Space/SpaceIssuesQuery.mjs +1 -1
  68. package/dist/network/graphql/builder/Queries/index.d.ts +1 -1
  69. package/dist/network/graphql/sdk/Queries/InitQuery.d.ts +1 -1
  70. package/dist/network/graphql/sdk/Queries/InitQuery.mjs +1 -1
  71. package/dist/network/index.mjs +8 -7
  72. package/dist/network/spaceEvents.d.ts +12 -6
  73. package/dist/network/spaceEvents.mjs +153 -154
  74. package/dist/realtime/client.mjs +123 -95
  75. package/dist/realtime/topics.mjs +18 -17
  76. package/dist/schema/anchor.d.ts +8 -0
  77. package/dist/schema/anchor.mjs +4 -0
  78. package/dist/schema/index.d.ts +2 -0
  79. package/dist/schema/index.mjs +6 -4
  80. package/dist/schema/serverElements.d.ts +6 -2
  81. package/dist/schema/serverElements.mjs +17 -16
  82. package/dist/schema/snippet.d.ts +7 -0
  83. package/dist/schema/snippet.mjs +9 -0
  84. package/dist/schema/wire.d.ts +11 -0
  85. package/dist/schema/wire.mjs +27 -0
  86. package/dist/server/actions/useImagesSync.d.ts +9 -0
  87. package/dist/server/actions/useImagesSync.mjs +7 -0
  88. package/dist/server/rsc/refreshRsc.mjs +8 -8
  89. package/dist/source/snapshot.mjs +23 -22
  90. package/dist/state/paintedState.mjs +13 -12
  91. package/dist/state/runtimeStatePersist.mjs +50 -49
  92. package/dist/store/index.d.ts +45 -45
  93. package/dist/style/breakpoints.d.ts +11 -0
  94. package/dist/style/breakpoints.mjs +8 -0
  95. package/dist/style/displayModes.d.ts +5 -0
  96. package/dist/style/displayModes.mjs +8 -0
  97. package/dist/style/fontValidation.mjs +52 -51
  98. package/dist/style/fonts.d.ts +0 -12
  99. package/dist/style/fonts.mjs +11 -11
  100. package/dist/style/index.d.ts +4 -0
  101. package/dist/style/index.mjs +11 -7
  102. package/dist/style/layoutGrid.d.ts +30 -0
  103. package/dist/style/layoutGrid.mjs +33 -0
  104. package/dist/style/notifications.d.ts +52 -0
  105. package/dist/style/notifications.mjs +55 -0
  106. package/dist/style/snippetStyle.d.ts +23 -0
  107. package/dist/style/snippetStyle.mjs +32 -0
  108. package/dist/style/styleConstants.d.ts +7 -2
  109. package/dist/style/styleConstants.mjs +10 -0
  110. package/dist/style/styleStates.d.ts +11 -2
  111. package/dist/style/styleStates.mjs +12 -9
  112. package/dist/theme/ThemeProvider.mjs +20 -20
  113. package/dist/types/CommonTypes.d.ts +3 -0
  114. package/dist/types/DevToolsTypes.d.ts +29 -4
  115. package/dist/types/EventBridgeTypes.d.ts +2 -2
  116. package/dist/types/PluginTypes.d.ts +1 -1
  117. package/dist/types/ResourceTypes.d.ts +2 -2
  118. package/dist/types/SchemaTypes.d.ts +62 -3
  119. package/dist/types/ServerTypes.d.ts +47 -0
  120. package/dist/types/SnippetTypes.d.ts +28 -0
  121. package/dist/types/StoreTypes.d.ts +25 -0
  122. package/dist/types/StyleTypes.d.ts +2 -1
  123. package/dist/types/StyleTypes.mjs +2 -2
  124. package/dist/types/index.d.ts +1 -1
  125. package/dist/types/index.mjs +2 -2
  126. package/dist/websockets/RTCodec.d.ts +1 -0
  127. package/dist/websockets/RTCodec.mjs +14 -12
  128. package/dist/websockets/index.mjs +2 -2
  129. package/package.json +115 -19
  130. package/tailwind.config.js +1 -6
  131. package/vite.config.ts +16 -4
  132. package/dist/network/graphql/builder/Mutations/Space/SpaceAddTemplateMutation.d.ts +0 -2
  133. package/dist/network/graphql/builder/Mutations/Space/SpaceAddTemplateMutation.mjs +0 -4
  134. package/dist/types/TemplateTypes.d.ts +0 -20
  135. /package/dist/types/{TemplateTypes.mjs → SnippetTypes.mjs} +0 -0
@@ -0,0 +1,38 @@
1
+ import { evaluateRuleGroup as e } from "../helpers/ruleEvaluator.mjs";
2
+ //#region src/flags/resolveFlags.ts
3
+ var t = [
4
+ "space",
5
+ "server",
6
+ "sdk",
7
+ "qa"
8
+ ], n = (e) => e ? {
9
+ authenticated: !0,
10
+ email: e.email,
11
+ username: e.username,
12
+ roles: e.roles
13
+ } : { authenticated: !1 }, r = [
14
+ "server",
15
+ "sdk",
16
+ "qa"
17
+ ], i = (e) => typeof e == "object" && !!e && "rules" in e && Array.isArray(e.rules) && e.rules.some((e) => typeof e == "object" && !!e && !("enabled" in e && e.enabled === !1)), a = (t, n) => Array.isArray(t.rules) ? t.rules.findIndex((t) => i(t.when) && e(t.when, n)) : -1, o = (e, t) => {
18
+ let n = a(e, t);
19
+ return n === -1 ? {
20
+ value: e.value,
21
+ layer: "space"
22
+ } : {
23
+ value: e.rules[n].value,
24
+ layer: "space",
25
+ rule: n
26
+ };
27
+ }, s = (e, t = {}, n = {}) => Object.fromEntries(Object.entries(e ?? {}).map(([e, i]) => [e, r.reduce((t, r) => {
28
+ let i = n[r]?.[e];
29
+ return typeof i == "boolean" ? {
30
+ value: i,
31
+ layer: r
32
+ } : t;
33
+ }, o(i, t))])), c = (e) => Object.fromEntries(Object.entries(e).map(([e, { value: t }]) => [e, t])), l = (e, t) => r.flatMap((n) => Object.keys(t[n] ?? {}).filter((t) => !Object.hasOwn(e ?? {}, t)).map((e) => ({
34
+ layer: n,
35
+ name: e
36
+ }))), u = (e, t) => !e || (t[e.name] ?? !1) === e.is;
37
+ //#endregion
38
+ export { t as FLAG_LAYERS, n as flagUserFromSSR, c as flagValues, i as hasConditions, u as passesFlagGate, s as resolveFlags, l as undeclaredFlagOverrides };
@@ -0,0 +1,11 @@
1
+ import { SchemaFlag } from '../types';
2
+ /** A flag name: what `{{ flags.<name> }}` reads, so it has to be a valid key in a template path. */
3
+ export declare const FLAG_NAME_PATTERN: RegExp;
4
+ /** A gate as authoring and MCP write it: `name` while the flag is on, `!name` while it is off. */
5
+ export declare const FLAG_GATE_PATTERN: RegExp;
6
+ export declare const isFlagName: (name: string) => boolean;
7
+ /**
8
+ * Whether a value is a flag as the resolver reads it — what every writer checks before storing one: a mutation, the
9
+ * live channel, the linter. A rule's `when` has to be a group; whether it says anything is the linter's to warn about.
10
+ */
11
+ export declare const isSchemaFlag: (value: unknown) => value is SchemaFlag;
@@ -0,0 +1,9 @@
1
+ import { isRecord as e } from "../helpers/isRecord.mjs";
2
+ //#region src/flags/schemaFlag.ts
3
+ var t = "[A-Za-z_][A-Za-z0-9_]*", n = RegExp(`^${t}$`), r = RegExp(`^!?${t}$`), i = /* @__PURE__ */ new Set([
4
+ "__proto__",
5
+ "constructor",
6
+ "prototype"
7
+ ]), a = (e) => n.test(e) && !i.has(e), o = (t) => e(t) && typeof t.value == "boolean" && (t.description === void 0 || typeof t.description == "string") && Array.isArray(t.rules) && t.rules.every((t) => e(t) && typeof t.value == "boolean" && e(t.when));
8
+ //#endregion
9
+ export { r as FLAG_GATE_PATTERN, n as FLAG_NAME_PATTERN, a as isFlagName, o as isSchemaFlag };
@@ -0,0 +1,13 @@
1
+ import { AuthContextValue } from '../types';
2
+ import { FlagResolution, FlagUser } from './resolveFlags';
3
+ /** The visitor as a flag's rule sees them, from what auth knows. */
4
+ export declare const flagUserFrom: ({ authenticated, user }: Partial<Pick<AuthContextValue, "authenticated" | "user">>) => FlagUser;
5
+ /**
6
+ * Every declared flag, resolved for where this render is and who is looking.
7
+ *
8
+ * What the `flags` source every element reads is published from. The router cannot wait for that source — it decides
9
+ * whether the page is gated off before any child renders — so it calls `resolveFlags` itself, with the same inputs.
10
+ * Stable while nothing changed, so the source is not written again on every navigation.
11
+ */
12
+ declare const useFlagResolution: (auth: Partial<Pick<AuthContextValue, "authenticated" | "user">>) => Record<string, FlagResolution>;
13
+ export default useFlagResolution;
@@ -0,0 +1,43 @@
1
+ import { resolveFlags as e } from "./resolveFlags.mjs";
2
+ import t from "../hooks/useStableValue.mjs";
3
+ import n from "../store/renderSettings.mjs";
4
+ import { useCommonStore as r } from "../store/index.mjs";
5
+ import { useMemo as i } from "react";
6
+ //#region src/flags/useFlagResolution.ts
7
+ var a = ({ authenticated: e, user: t }) => {
8
+ let n = t?.details, r = { authenticated: e === !0 };
9
+ return n ? {
10
+ ...r,
11
+ email: n.email,
12
+ username: n.username,
13
+ roles: n.roles
14
+ } : r;
15
+ }, o = (o) => {
16
+ let { environment: s } = n(), [[c, l, u, d, f]] = r([
17
+ "schema.flags",
18
+ "navigation.routeParams",
19
+ "navigation.queryParams",
20
+ "navigation.hostname",
21
+ "flags.overrides"
22
+ ]), { authenticated: p, user: m } = o, h = i(() => a({
23
+ authenticated: p,
24
+ user: m
25
+ }), [p, m]);
26
+ return t(i(() => e(c, {
27
+ environment: s,
28
+ hostname: d,
29
+ routeParams: l,
30
+ queryParams: u,
31
+ user: h
32
+ }, f), [
33
+ c,
34
+ s,
35
+ d,
36
+ l,
37
+ u,
38
+ h,
39
+ f
40
+ ]));
41
+ };
42
+ //#endregion
43
+ export { o as default, a as flagUserFrom };
@@ -0,0 +1,10 @@
1
+ /**
2
+ * An event's target read as a DOM node. `instanceof Node` answers false for a target inside an iframe — each window has
3
+ * its own `Node` — and the builder listens on its canvas iframe's document, so these test the node's own type instead.
4
+ */
5
+ export declare const isNodeTarget: (target: EventTarget | null) => target is Node;
6
+ /** An event's target as the node it is, for `contains`; null when it is not a node (a window, an XHR). */
7
+ export declare const nodeOf: (target: EventTarget | null) => Node | null;
8
+ export declare const isElementTarget: (target: EventTarget | null) => target is Element;
9
+ /** An event's target as the element it is, for `closest`; null when it is a text node or no node at all. */
10
+ export declare const elementOf: (target: EventTarget | null) => Element | null;
@@ -0,0 +1,4 @@
1
+ //#region src/helpers/eventTarget.ts
2
+ var e = (e) => e !== null && "nodeType" in e && typeof e.nodeType == "number", t = (t) => e(t) ? t : null, n = (t) => e(t) && t.nodeType === Node.ELEMENT_NODE, r = (e) => n(e) ? e : null;
3
+ //#endregion
4
+ export { r as elementOf, n as isElementTarget, e as isNodeTarget, t as nodeOf };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * A remote picture resized by the server that renders the page — the one vocabulary both ends speak.
3
+ *
4
+ * The widths are a closed set rather than whatever a page asks for: each one is a file the server makes and keeps,
5
+ * so a free width would let anybody fill its disk one request at a time.
6
+ */
7
+ /** Where a page server that resizes images answers. */
8
+ export declare const IMAGE_PATH = "/_plitzi/img";
9
+ /** Every width a picture is offered at, narrowest first. */
10
+ export declare const IMAGE_WIDTHS: readonly [320, 480, 640, 768, 960, 1280, 1600, 1920];
11
+ export type ImageWidth = (typeof IMAGE_WIDTHS)[number];
12
+ export declare const isImageWidth: (width: number) => width is ImageWidth;
13
+ /** A picture another site serves — the only kind there is anything to resize; a path of this site is served as it is. */
14
+ export declare const isRemoteImage: (src: string) => boolean;
15
+ /** The address of `src` at `width` on the endpoint. */
16
+ export declare const imageUrl: (endpoint: string, src: string, width: ImageWidth) => string;
17
+ /** Every width as a `srcset`, for the browser to pick the one its layout needs. */
18
+ export declare const imageSrcSet: (endpoint: string, src: string) => string;
@@ -0,0 +1,13 @@
1
+ //#region src/helpers/images.ts
2
+ var e = "/_plitzi/img", t = [
3
+ 320,
4
+ 480,
5
+ 640,
6
+ 768,
7
+ 960,
8
+ 1280,
9
+ 1600,
10
+ 1920
11
+ ], n = (e) => t.some((t) => t === e), r = (e) => /^https?:\/\//i.test(e), i = (e, t, n) => `${e}?url=${encodeURIComponent(t)}&w=${String(n)}`, a = (e, n) => t.map((t) => `${i(e, n, t)} ${String(t)}w`).join(", ");
12
+ //#endregion
13
+ export { e as IMAGE_PATH, t as IMAGE_WIDTHS, a as imageSrcSet, i as imageUrl, n as isImageWidth, r as isRemoteImage };
@@ -2,9 +2,12 @@ import { default as fetchManifest } from './fetchManifest';
2
2
  import { default as generateFacade } from './generateFacade';
3
3
  import { default as syntaxHighlight } from './syntaxHighlight';
4
4
  export * from './cookies';
5
+ export * from './eventTarget';
5
6
  export * from './fetchManifest';
6
7
  export * from './formatDate';
8
+ export * from './interval';
7
9
  export * from './isDate';
10
+ export * from './isRecord';
8
11
  export * from './generateFacade';
9
12
  export * from './reducerOrigin';
10
13
  export * from './ruleEvaluator';
@@ -1,18 +1,21 @@
1
- import { filters as e } from "./twigWrapper/filters/filters.mjs";
2
- import { processTwig as t, processTwigParam as n, processTwigValue as r } from "./twigWrapper/processTwig/processTwig.mjs";
3
- import { hasTemplateSyntax as i } from "./twigWrapper/tokens/hasTemplateSyntax.mjs";
4
- import { hasValidToken as a } from "./twigWrapper/tokens/hasValidToken.mjs";
5
- import { MAX_PARAM_PASSES as o, resolveStepParam as s } from "./twigWrapper/processTwig/resolveStepParam.mjs";
6
- import { inspectTemplate as c } from "./twigWrapper/inspectTemplate.mjs";
7
- import { templatePaths as l, templateRootNames as u } from "./twigWrapper/templateRoots.mjs";
8
- import d from "./fetchManifest.mjs";
9
- import f from "./generateFacade.mjs";
10
- import p from "./syntaxHighlight.mjs";
11
- import { cookieFromHeader as m, documentCookies as h } from "./cookies.mjs";
12
- import { formatDate as g, formatDateUTC as _, formatFromNow as v, formatUTCToLocal as y, getDurationMs as b, isValidFormat as x, parseDate as S, toUnixSeconds as C } from "./formatDate.mjs";
13
- import { isDate as w } from "./isDate.mjs";
14
- import { isUserEdit as T } from "./reducerOrigin.mjs";
15
- import { evaluateRuleGroup as E } from "./ruleEvaluator.mjs";
16
- import { ParamsFromURL as D, delay as O, emptyObject as k, getDisplayName as A, getKeyDecoded as j, getPathsFromObeject as M, hexToRGB as N, isInViewport as P, makeId as F } from "./utils.mjs";
17
- import { disableReactDevTools as I } from "./security.mjs";
18
- export { o as MAX_PARAM_PASSES, D as ParamsFromURL, m as cookieFromHeader, O as delay, I as disableReactDevTools, h as documentCookies, k as emptyObject, E as evaluateRuleGroup, d as fetchManifest, e as filters, g as formatDate, _ as formatDateUTC, v as formatFromNow, y as formatUTCToLocal, f as generateFacade, A as getDisplayName, b as getDurationMs, j as getKeyDecoded, M as getPathsFromObeject, i as hasTemplateSyntax, a as hasValidToken, N as hexToRGB, c as inspectTemplate, w as isDate, P as isInViewport, T as isUserEdit, x as isValidFormat, F as makeId, S as parseDate, t as processTwig, n as processTwigParam, r as processTwigValue, s as resolveStepParam, p as syntaxHighlight, l as templatePaths, u as templateRootNames, C as toUnixSeconds };
1
+ import { isRecord as e } from "./isRecord.mjs";
2
+ import { filters as t } from "./twigWrapper/filters/filters.mjs";
3
+ import { processTwig as n, processTwigParam as r, processTwigValue as i } from "./twigWrapper/processTwig/processTwig.mjs";
4
+ import { hasTemplateSyntax as a } from "./twigWrapper/tokens/hasTemplateSyntax.mjs";
5
+ import { hasValidToken as o } from "./twigWrapper/tokens/hasValidToken.mjs";
6
+ import { MAX_PARAM_PASSES as s, resolveStepParam as c } from "./twigWrapper/processTwig/resolveStepParam.mjs";
7
+ import { inspectTemplate as l } from "./twigWrapper/inspectTemplate.mjs";
8
+ import { templatePaths as u, templateRootNames as d } from "./twigWrapper/templateRoots.mjs";
9
+ import f from "./fetchManifest.mjs";
10
+ import p from "./generateFacade.mjs";
11
+ import m from "./syntaxHighlight.mjs";
12
+ import { cookieFromHeader as h, documentCookies as g } from "./cookies.mjs";
13
+ import { elementOf as _, isElementTarget as v, isNodeTarget as y, nodeOf as b } from "./eventTarget.mjs";
14
+ import { formatDate as x, formatDateUTC as S, formatFromNow as C, formatUTCToLocal as w, getDurationMs as T, isValidFormat as E, parseDate as D, toUnixSeconds as O } from "./formatDate.mjs";
15
+ import { INTERVAL_TRIGGER as k, MIN_INTERVAL_MS as A, intervalOf as j } from "./interval.mjs";
16
+ import { isDate as M } from "./isDate.mjs";
17
+ import { isUserEdit as N } from "./reducerOrigin.mjs";
18
+ import { evaluateRuleGroup as P } from "./ruleEvaluator.mjs";
19
+ import { ParamsFromURL as F, delay as I, emptyObject as L, getDisplayName as R, getKeyDecoded as z, getPathsFromObeject as B, hexToRGB as V, isInViewport as H, makeId as U } from "./utils.mjs";
20
+ import { disableReactDevTools as W } from "./security.mjs";
21
+ export { k as INTERVAL_TRIGGER, s as MAX_PARAM_PASSES, A as MIN_INTERVAL_MS, F as ParamsFromURL, h as cookieFromHeader, I as delay, W as disableReactDevTools, g as documentCookies, _ as elementOf, L as emptyObject, P as evaluateRuleGroup, f as fetchManifest, t as filters, x as formatDate, S as formatDateUTC, C as formatFromNow, w as formatUTCToLocal, p as generateFacade, R as getDisplayName, T as getDurationMs, z as getKeyDecoded, B as getPathsFromObeject, a as hasTemplateSyntax, o as hasValidToken, V as hexToRGB, l as inspectTemplate, j as intervalOf, M as isDate, v as isElementTarget, H as isInViewport, y as isNodeTarget, e as isRecord, N as isUserEdit, E as isValidFormat, U as makeId, b as nodeOf, D as parseDate, n as processTwig, r as processTwigParam, i as processTwigValue, c as resolveStepParam, m as syntaxHighlight, u as templatePaths, d as templateRootNames, O as toUnixSeconds };
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Repeating a flow every so often — an autoplay, a clock, a poll of something on the page — with no plugin to write.
3
+ *
4
+ * The element listening, the interactions manager and authoring read this one module, so the trigger's name, its
5
+ * floor and what it carries cannot drift between them.
6
+ */
7
+ /** The trigger a repeating flow starts on: fired once per tick of each interval its element's flows declare. */
8
+ export declare const INTERVAL_TRIGGER = "onInterval";
9
+ /** Below a quarter of a second, a flow that repeats is a busy loop that happens to wait. */
10
+ export declare const MIN_INTERVAL_MS = 250;
11
+ export type IntervalTriggerPayload = {
12
+ /** The interval that ticked, in milliseconds: the flows that run are the ones declared with it. */
13
+ interval: number;
14
+ /** How many times it has ticked since the element appeared — `{{ tick.count }}` with `named('tick', …)`. */
15
+ count: number;
16
+ };
17
+ /** An interval a flow declares, read as the trigger reads it: a whole number of milliseconds, at least the floor. */
18
+ export declare const intervalOf: (value: unknown) => number | undefined;
@@ -0,0 +1,7 @@
1
+ //#region src/helpers/interval.ts
2
+ var e = "onInterval", t = 250, n = (e) => {
3
+ let t = typeof e == "string" && e.trim() !== "" ? Number(e) : e;
4
+ return typeof t == "number" && Number.isInteger(t) && t >= 250 ? t : void 0;
5
+ };
6
+ //#endregion
7
+ export { e as INTERVAL_TRIGGER, t as MIN_INTERVAL_MS, n as intervalOf };
@@ -0,0 +1,2 @@
1
+ /** A plain object read off untyped data — JSON, a message, a document — and not an array, which is an object too. */
2
+ export declare const isRecord: (value: unknown) => value is Record<string, unknown>;
@@ -0,0 +1,4 @@
1
+ //#region src/helpers/isRecord.ts
2
+ var e = (e) => typeof e == "object" && !!e && !Array.isArray(e);
3
+ //#endregion
4
+ export { e as isRecord };
@@ -0,0 +1,42 @@
1
+ /**
2
+ * What the scroll steps and the `onScroll` trigger read and write, as plain arithmetic over a box's sizes — so the
3
+ * meaning of `'80%'` or `'end'` is decided once, and tested without a browser.
4
+ */
5
+ /** A box that scrolls, measured: what `Element` has, and all these functions read. */
6
+ export type ScrollBox = {
7
+ scrollLeft: number;
8
+ scrollTop: number;
9
+ scrollWidth: number;
10
+ scrollHeight: number;
11
+ clientWidth: number;
12
+ clientHeight: number;
13
+ };
14
+ /** What `onScroll` hands its flow: where the box is, and whether it is at either end of the way it scrolls. */
15
+ export type ScrollTriggerPayload = {
16
+ x: number;
17
+ y: number;
18
+ atStart: boolean;
19
+ atEnd: boolean;
20
+ };
21
+ export declare const SCROLL_BEHAVIORS: readonly ["smooth", "auto"];
22
+ export type ScrollStepBehavior = (typeof SCROLL_BEHAVIORS)[number];
23
+ /** Where `scrollIntoView` lands an element, on each axis. */
24
+ export declare const SCROLL_POSITIONS: readonly ["start", "center", "end", "nearest"];
25
+ export type ScrollStepPosition = (typeof SCROLL_POSITIONS)[number];
26
+ /**
27
+ * A distance to move: pixels (`240`, `'240'`, `'240px'`) or a share of what the box shows (`'80%'` of its width) —
28
+ * negative goes back. `undefined` for nothing to move, or for text that is not a length.
29
+ */
30
+ export declare const scrollDistance: (value: unknown, visible: number) => number | undefined;
31
+ /**
32
+ * A place to go to on one axis: `'start'`, `'end'`, pixels from the start, or a share of the whole way (`'50%'` is
33
+ * half-way). `undefined` leaves that axis where it is.
34
+ */
35
+ export declare const scrollPosition: (value: unknown, scrollSize: number, clientSize: number) => number | undefined;
36
+ /**
37
+ * Where a box is, for `onScroll`. The ends are those of the way it scrolls — across for a row wider than its box,
38
+ * down otherwise — which is what an arrow that hides at the end of a carousel asks.
39
+ */
40
+ export declare const scrollState: (box: ScrollBox) => ScrollTriggerPayload;
41
+ /** The trigger a scroll fires, its action name in a flow. */
42
+ export declare const SCROLL_TRIGGER = "onScroll";
@@ -0,0 +1,30 @@
1
+ //#region src/helpers/scroll.ts
2
+ var e = ["smooth", "auto"], t = [
3
+ "start",
4
+ "center",
5
+ "end",
6
+ "nearest"
7
+ ], n = 1, r = /^(-?\d+(?:\.\d+)?)(px|%)?$/, i = (e, t) => {
8
+ if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
9
+ if (typeof e != "string") return;
10
+ let n = r.exec(e.trim());
11
+ if (!n) return;
12
+ let i = Number(n[1]);
13
+ return n[2] === "%" ? i / 100 * t : i;
14
+ }, a = (e, t, n) => {
15
+ let r = Math.max(t - n, 0);
16
+ if (e === "start") return 0;
17
+ if (e === "end") return r;
18
+ let a = i(e, r);
19
+ return a === void 0 ? void 0 : Math.min(Math.max(a, 0), r);
20
+ }, o = (e) => {
21
+ let t = e.scrollWidth - e.clientWidth > n, r = t ? e.scrollLeft : e.scrollTop, i = t ? e.scrollWidth - e.clientWidth : e.scrollHeight - e.clientHeight;
22
+ return {
23
+ x: Math.round(e.scrollLeft),
24
+ y: Math.round(e.scrollTop),
25
+ atStart: r <= n,
26
+ atEnd: r >= i - n
27
+ };
28
+ }, s = "onScroll";
29
+ //#endregion
30
+ export { e as SCROLL_BEHAVIORS, t as SCROLL_POSITIONS, s as SCROLL_TRIGGER, i as scrollDistance, a as scrollPosition, o as scrollState };
@@ -2,7 +2,7 @@ import { isDottedPath as e } from "../charClass.mjs";
2
2
  import { lex as t } from "../Lexer/Lexer.mjs";
3
3
  import { parse as n } from "../Parser/Parser.mjs";
4
4
  //#region src/helpers/twigWrapper/TemplateCache/TemplateCache.ts
5
- var r = /* @__PURE__ */ new Map(), i = 256, a = {
5
+ var r = /* @__PURE__ */ new Map(), i = 1024, a = {
6
6
  hits: 0,
7
7
  misses: 0
8
8
  }, o = () => ({
@@ -151,7 +151,20 @@ var e = Symbol("twigArrowParams"), t = (e) => e == null || e === "", n = (e, t)
151
151
  seconds: Number(i("second")),
152
152
  weekday: f.indexOf(i("weekday"))
153
153
  };
154
- }, _ = {
154
+ }, _ = (e) => {
155
+ if (typeof e == "number") return Number.isFinite(e) ? e : void 0;
156
+ if (typeof e == "string" && e.trim() !== "") {
157
+ let t = Number(e);
158
+ return Number.isFinite(t) ? t : void 0;
159
+ }
160
+ }, v = (e, t, n) => {
161
+ for (let r of [t == null ? "en" : i(t), "en"]) try {
162
+ return new Intl.NumberFormat(r, n).format(e);
163
+ } catch {
164
+ continue;
165
+ }
166
+ return String(e);
167
+ }, y = {
155
168
  raw: (e) => u(e),
156
169
  to_json: (e) => r(e),
157
170
  json_encode: (e) => r(e),
@@ -220,6 +233,29 @@ var e = Symbol("twigArrowParams"), t = (e) => e == null || e === "", n = (e, t)
220
233
  let s = o.split(".");
221
234
  return s[0] = s[0].replace(/\B(?=(\d{3})+(?!\d))/g, a), s.join(r);
222
235
  },
236
+ currency: (e, t) => {
237
+ let n = _(e);
238
+ if (n === void 0 || t.length === 0) return e;
239
+ let r = t[2], a = typeof r == "object" && !!r && "trimZeros" in r && r.trimZeros === !0 && Number.isInteger(n);
240
+ return v(n, t[1], {
241
+ style: "currency",
242
+ currency: i(t[0]),
243
+ ...a ? {
244
+ minimumFractionDigits: 0,
245
+ maximumFractionDigits: 0
246
+ } : {}
247
+ });
248
+ },
249
+ percent: (e, t) => {
250
+ let n = _(e);
251
+ if (n === void 0) return e;
252
+ let r = Number(t[0]) || 0;
253
+ return v(n, t[1], {
254
+ style: "percent",
255
+ minimumFractionDigits: 0,
256
+ maximumFractionDigits: r
257
+ });
258
+ },
223
259
  sort: (t, r) => {
224
260
  if (!Array.isArray(t)) return t;
225
261
  let i = [...t], a = r[0];
@@ -447,4 +483,4 @@ var e = Symbol("twigArrowParams"), t = (e) => e == null || e === "", n = (e, t)
447
483
  }
448
484
  };
449
485
  //#endregion
450
- export { e as ARROW_PARAMS, c as RAW_MARKER, _ as filters, l as isRawMarker, d as unwrapRaw, u as wrapRaw };
486
+ export { e as ARROW_PARAMS, c as RAW_MARKER, y as filters, l as isRawMarker, d as unwrapRaw, u as wrapRaw };
@@ -1,5 +1,6 @@
1
+ import { isRecord as e } from "../helpers/isRecord.mjs";
1
2
  //#region src/history/describe.ts
2
- var e = (e) => typeof e == "object" && !!e && !Array.isArray(e), t = (n, r, i = "") => e(n) && e(r) ? [.../* @__PURE__ */ new Set([...Object.keys(n), ...Object.keys(r)])].flatMap((e) => t(n[e], r[e], i ? `${i}.${e}` : e)) : JSON.stringify(n) === JSON.stringify(r) ? [] : [{
3
+ var t = (n, r, i = "") => e(n) && e(r) ? [.../* @__PURE__ */ new Set([...Object.keys(n), ...Object.keys(r)])].flatMap((e) => t(n[e], r[e], i ? `${i}.${e}` : e)) : JSON.stringify(n) === JSON.stringify(r) ? [] : [{
3
4
  path: i,
4
5
  ...n === void 0 ? {} : { before: n },
5
6
  ...r === void 0 ? {} : { after: r }
@@ -28,6 +29,7 @@ var e = (e) => typeof e == "object" && !!e && !Array.isArray(e), t = (n, r, i =
28
29
  component: "component",
29
30
  folder: "folder",
30
31
  variable: "variable",
32
+ flag: "feature flag",
31
33
  setting: "setting",
32
34
  selector: "class",
33
35
  globalStyle: "global style for",
@@ -16,7 +16,7 @@ export declare const sameValue: (a: unknown, b: unknown) => boolean;
16
16
  */
17
17
  export declare const jsonCopy: <T>(value: T) => T;
18
18
  /** The part of a schema a history reads: what is stored, never what the runtime derives from it. */
19
- export type HistorySchema = Pick<Schema, 'flat' | 'pages' | 'pageFolders' | 'variables' | 'settings' | 'definition' | 'components'>;
19
+ export type HistorySchema = Pick<Schema, 'flat' | 'pages' | 'pageFolders' | 'variables' | 'flags' | 'settings' | 'definition' | 'components'>;
20
20
  /**
21
21
  * What changed between two versions of a schema, entity by entity.
22
22
  *
@@ -31,6 +31,7 @@ var e = (t, n) => {
31
31
  ...n("component", o(e), o(t)),
32
32
  ...n("folder", r(e.pageFolders, (e) => e.id), r(t.pageFolders, (e) => e.id)),
33
33
  ...n("variable", r(e.variables, (e) => e.name), r(t.variables, (e) => e.name)),
34
+ ...n("flag", e.flags ?? {}, t.flags ?? {}),
34
35
  ...n("setting", {
35
36
  ...i("settings", e.settings),
36
37
  ...i("definition", e.definition),
@@ -11,7 +11,7 @@ export type ChangeOrigin = 'builder' | 'mcp' | 'coworker' | 'autofix' | 'api' |
11
11
  * (a bare element selector), an id style, a design token (`<category>/<name>`), a font family, a style setting
12
12
  * (`theme`, `mode`). Functions: a file of their source, by its path (`index.ts`, `lib/feed.ts`).
13
13
  */
14
- export type ChangeKind = 'element' | 'component' | 'folder' | 'variable' | 'setting' | 'selector' | 'globalStyle' | 'idStyle' | 'token' | 'font' | 'file';
14
+ export type ChangeKind = 'element' | 'component' | 'folder' | 'variable' | 'flag' | 'setting' | 'selector' | 'globalStyle' | 'idStyle' | 'token' | 'font' | 'file';
15
15
  /** One entity that changed, whole, before and after: the field-level difference is derived from the two. */
16
16
  export type ChangeEntry = {
17
17
  kind: ChangeKind;
@@ -1,5 +1,5 @@
1
- import e from "./useFontHead.mjs";
2
- import t from "./useNetwork.mjs";
3
- import n, { PlitziServiceContext as r, PlitziServiceProvider as i } from "./usePlitziServiceContext.mjs";
4
- import a from "./useStableValue.mjs";
5
- export { r as PlitziServiceContext, i as PlitziServiceProvider, e as useFontHead, t as useNetwork, n as usePlitziServiceContext, a as useStableValue };
1
+ import e from "./useStableValue.mjs";
2
+ import t from "./useFontHead.mjs";
3
+ import n from "./useNetwork.mjs";
4
+ import r, { PlitziServiceContext as i, PlitziServiceProvider as a } from "./usePlitziServiceContext.mjs";
5
+ export { i as PlitziServiceContext, a as PlitziServiceProvider, t as useFontHead, n as useNetwork, r as usePlitziServiceContext, e as useStableValue };
package/dist/index.d.ts CHANGED
@@ -16,3 +16,4 @@ export * from './theme';
16
16
  export * from './server';
17
17
  export * from './state';
18
18
  export * from './history';
19
+ export * from './flags';