@plitzi/sdk-schema 0.37.8 → 0.37.10

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.
@@ -0,0 +1,130 @@
1
+ import { isValidElementId as e, repointIds as t, uniqueElementId as n } from "./elementId.mjs";
2
+ import { descendants as r } from "./elementTree.mjs";
3
+ import i from "./FlatMap.mjs";
4
+ import { jsonCopy as a } from "@plitzi/sdk-shared/history";
5
+ //#region src/helpers/components.ts
6
+ var o = /* @__PURE__ */ new Set([
7
+ "referenceType",
8
+ "referenceId",
9
+ "slot",
10
+ "className",
11
+ "style",
12
+ "children",
13
+ "ref",
14
+ "id"
15
+ ]), s = /^[A-Za-z][A-Za-z0-9_]*$/, c = (e) => s.test(e) ? o.has(e) ? `"${e}" is an attribute every instance already has` : null : `"${e}" is not a valid prop name: start with a letter, then letters, numbers and underscores — it is read as {{ props.${e} }}`, l = (e) => [{ flat: e.flat }, ...Object.values(e.components).map((e) => ({
16
+ flat: e.flat,
17
+ componentId: e.id
18
+ }))], u = (e, t) => l(e).find((e) => Object.hasOwn(e.flat, t)), d = (e) => new Set(l(e).flatMap((e) => Object.keys(e.flat))), f = (e, t, n) => {
19
+ let r = u(e, t);
20
+ if (!r) return;
21
+ let a = l(e).filter((e) => e.flat !== r.flat);
22
+ return new i({
23
+ flat: r.flat,
24
+ pages: r.componentId ? void 0 : e.pages,
25
+ mintId: n,
26
+ takenElsewhere: (e) => a.some((t) => Object.hasOwn(t.flat, e))
27
+ });
28
+ }, p = (e, t) => Object.hasOwn(e.components, t) ? e.components[t] : void 0, m = (e, t) => e.definition.type === "reference" && e.attributes.referenceType === "component" && (t === void 0 || e.attributes.referenceId === t), h = (e, t) => l(e).flatMap((e) => Object.values(e.flat).filter((e) => m(e, t))), g = (e, n, r) => {
29
+ let i = f(e, n);
30
+ if (!i) return !1;
31
+ let a = i.renameElement(n, r);
32
+ if (!a || n === r) return a;
33
+ for (let o of l(e)) o.flat !== i.flat && a.push(...t(o.flat, { [n]: r }));
34
+ for (let t of Object.values(e.components)) t.rootId === n && (t.rootId = r), t.slots?.includes(n) && (t.slots = t.slots.map((e) => e === n ? r : e));
35
+ return [...new Set(a)];
36
+ }, _ = (e, t) => {
37
+ for (let t of Object.keys(e.props ?? {})) {
38
+ let e = c(t);
39
+ if (e) return e;
40
+ }
41
+ let n = (e.slots ?? []).find((e) => !Object.hasOwn(t, e));
42
+ return n ? `slot "${n}" is not an element of the component` : null;
43
+ }, v = (e, t, n) => ({
44
+ id: t,
45
+ attributes: {
46
+ referenceType: "component",
47
+ referenceId: e.id
48
+ },
49
+ definition: {
50
+ label: e.label ?? e.id,
51
+ type: "reference",
52
+ items: [],
53
+ bindings: {},
54
+ parentId: n.definition.parentId,
55
+ rootId: n.definition.rootId,
56
+ styleSelectors: { base: "" },
57
+ initialState: { visibility: !0 }
58
+ }
59
+ }), y = (t, n, i) => {
60
+ if (!e(n.id) || Object.hasOwn(t.components, n.id)) return !1;
61
+ if (!i) {
62
+ let e = n.flat[n.rootId], r = d(t);
63
+ return !e || e.definition.parentId || Object.keys(n.flat).some((e) => r.has(e)) || _(n, n.flat) ? !1 : (t.components[n.id] = n, !0);
64
+ }
65
+ let { elementId: a, instanceId: o } = i, s = u(t, a), c = s?.flat[a], l = c?.definition.parentId ? s?.flat[c.definition.parentId] : void 0;
66
+ if (!s || !c || !l?.definition.items || !e(o) || d(t).has(o)) return !1;
67
+ let f = {};
68
+ for (let e of [a, ...r(s.flat, a)]) {
69
+ let { parentId: t, ...n } = s.flat[e].definition;
70
+ f[e] = {
71
+ ...s.flat[e],
72
+ definition: {
73
+ ...n,
74
+ ...e === a ? {} : { parentId: t },
75
+ rootId: a
76
+ }
77
+ };
78
+ }
79
+ let p = {
80
+ ...n,
81
+ rootId: a,
82
+ flat: f
83
+ };
84
+ if (_(p, f)) return !1;
85
+ for (let e of Object.keys(f)) delete s.flat[e];
86
+ return s.flat[o] = v(p, o, c), l.definition.items = l.definition.items.map((e) => e === a ? o : e), t.components[p.id] = p, !0;
87
+ }, b = (e, t, n) => {
88
+ let r = p(e, t);
89
+ return !r || _({
90
+ ...r,
91
+ ...n
92
+ }, r.flat) ? !1 : (e.components[t] = {
93
+ ...r,
94
+ ...n
95
+ }, !0);
96
+ }, x = (e, t) => !Object.hasOwn(e.components, t) || h(e, t).length > 0 ? !1 : (delete e.components[t], !0), S = (e, i) => {
97
+ let o = u(e, i), s = o?.flat[i], { referenceId: c } = s?.attributes ?? {}, l = s && m(s) && typeof c == "string" ? p(e, c) : void 0, f = s?.definition.parentId ? o?.flat[s.definition.parentId] : void 0;
98
+ if (!o || !s || !l || !f?.definition.items) return !1;
99
+ let h = s.definition.items ?? [], g = (e) => {
100
+ let { slot: t } = o.flat[e].attributes;
101
+ return typeof t == "string" ? t : l.slots?.[0];
102
+ };
103
+ if (h.some((e) => !l.slots?.includes(g(e) ?? ""))) return !1;
104
+ let _ = d(e);
105
+ _.delete(i);
106
+ let v = [l.rootId, ...r(l.flat, l.rootId)], y = {};
107
+ for (let e of v) y[e] = n(e, (e) => _.has(e)), _.add(y[e]);
108
+ let b = {};
109
+ for (let e of v) {
110
+ let t = a(l.flat[e]);
111
+ t.definition.rootId = s.definition.rootId, b[e] = t;
112
+ }
113
+ t(b, y);
114
+ let x = b[y[l.rootId]];
115
+ x.definition.parentId = s.definition.parentId;
116
+ for (let e of h) {
117
+ let t = b[y[g(e) ?? ""]], n = o.flat[e], { slot: r, ...i } = n.attributes;
118
+ o.flat[e] = {
119
+ ...n,
120
+ attributes: i,
121
+ definition: {
122
+ ...n.definition,
123
+ parentId: t.id
124
+ }
125
+ }, t.definition.items = [...t.definition.items ?? [], e];
126
+ }
127
+ return Object.assign(o.flat, b), delete o.flat[i], f.definition.items = f.definition.items.map((e) => e === i ? x.id : e), x.id;
128
+ };
129
+ //#endregion
130
+ export { o as RESERVED_PROP_NAMES, y as addComponent, p as componentNamed, S as detachInstance, d as documentIds, f as flatMapOf, h as instancesOf, m as isInstance, c as propNameProblem, x as removeComponent, g as renameElement, u as treeOf, l as treesOf, b as updateComponent };
@@ -11,9 +11,9 @@ export declare const isValidElementId: (id: string) => boolean;
11
11
  * collapse, and a leading non-letter is dropped — so a name is editable as prose in the builder's tree and still
12
12
  * lands as a valid key. Empty when nothing usable survives, which the caller reports rather than storing. */
13
13
  export declare const slugifyElementId: (value: string) => string;
14
- /** Every id currently in use, so a new one can be checked or minted against it. Uniqueness is per DOCUMENT — a
15
- * space schema, and each segment separately — which is what makes a lookup a `flat` key access. A segment used on
16
- * several pages repeats its ids in the rendered tree; `rootId`/`referenceId` are what tell those apart. */
14
+ /** Every id in use in one tree, so a new one can be checked or minted against it. Uniqueness spans the DOCUMENT —
15
+ * the space's `flat` and every component's (`documentIds`) — which is what makes a lookup a `flat` key access. A
16
+ * component placed several times repeats its ids in the rendered tree; each instance's scope tells those apart. */
17
17
  export declare const takenIds: (flat: Record<Element["id"], Element>) => Set<string>;
18
18
  /** Why `id` cannot be used in this document, phrased for a person, or null when it is free and well formed.
19
19
  * `ignoreElementId` exempts the element being edited, so re-saving an element its own id is not a conflict. */
@@ -66,7 +66,7 @@ export declare const repointIds: (flat: Record<Element["id"], Element>, map: Rec
66
66
  * Renames only the elements of an incoming set whose names this document has already taken, and repoints the set's
67
67
  * own references onto the new names.
68
68
  *
69
- * What a template drop and a cross-document paste both need. Renaming everything would be simpler and worse: the
69
+ * What a snippet drop and a cross-document paste both need. Renaming everything would be simpler and worse: the
70
70
  * names an author gave the template are the reason it is readable, and a document that had no `hero` should get
71
71
  * one called `hero`. Returns the renaming it applied, so a caller can report what it had to change.
72
72
  */
@@ -78,6 +78,8 @@ var e = /^[A-Za-z](?:[A-Za-z0-9_-]*[A-Za-z0-9_])?$/, t = (t) => e.test(t), n = (
78
78
  let r = o[n];
79
79
  typeof r == "string" && t[r] && (!i || i(o)) && (o[n] = t[r], e = !0);
80
80
  }
81
+ let { slot: s } = o;
82
+ typeof s == "string" && t[s] && (o.slot = t[s], e = !0);
81
83
  for (let n of Object.values(r.bindings ?? {})) for (let r of n) {
82
84
  let n = p(r.source, t);
83
85
  n !== r.source && (r.source = n, e = !0), r.transformers && g(r.transformers, t) && (e = !0), r.when && g(r.when, t) && (e = !0);
@@ -0,0 +1,32 @@
1
+ import { Element, Schema, SnippetStyle, Style } from '@plitzi/sdk-shared';
2
+ type Elements = Record<Element['id'], Element>;
3
+ /**
4
+ * A snippet, fitted to the space it is about to enter: its elements and its classes under names that are free there.
5
+ *
6
+ * A snippet arrives from a document nobody here has seen, and the names it brought may not be free — dropping the same
7
+ * snippet twice is enough. Only what collides changes, and everything that pointed at it is repointed with it: the
8
+ * names an author gave are why the snippet reads well, and a space with no `hero` should get one called `hero`.
9
+ *
10
+ * - An element whose id the space holds is renamed (`remapCollidingIds`).
11
+ * - A class the space uses for something else is renamed, in the snippet's style and on the elements that wear it, so
12
+ * the space's own `.card` is not restyled by the snippet's. One that says the same is shared.
13
+ * - Rules for an element type, and tokens, are left for the merge (`mergeSnippetStyle`), which adds what the space
14
+ * lacks and keeps what it has.
15
+ *
16
+ * Decided once, where somebody dropped it, and carried by the insert from there: the editor, the server it is saved to
17
+ * and every collaborator it is broadcast to then insert the same names, and one that stopped being free on the way is
18
+ * refused there rather than stored under another name. Copied first: the snippet belongs to whoever passed it.
19
+ */
20
+ declare const fitSnippet: (space: {
21
+ schema: Pick<Schema, "flat" | "components">;
22
+ style: Pick<Style, "platform">;
23
+ }, snippet: {
24
+ data: Element;
25
+ initialItems?: Elements;
26
+ style?: SnippetStyle;
27
+ }) => {
28
+ data: Element;
29
+ initialItems: Elements;
30
+ style?: SnippetStyle;
31
+ };
32
+ export default fitSnippet;
@@ -0,0 +1,71 @@
1
+ import { remapCollidingIds as e } from "./elementId.mjs";
2
+ import { documentIds as t } from "./components.mjs";
3
+ import { isDisplayMode as n } from "@plitzi/sdk-shared/style/displayModes";
4
+ import { sameSelector as r, selectorsOf as i } from "@plitzi/sdk-shared/style/snippetStyle";
5
+ import a from "@plitzi/sdk-style/helpers/processSelector";
6
+ //#region src/helpers/fitSnippet.ts
7
+ var o = (e, t) => {
8
+ let n = 2;
9
+ for (; t.has(`${e}-${n}`);) n += 1;
10
+ return `${e}-${n}`;
11
+ }, s = (e, t) => {
12
+ let n = /* @__PURE__ */ new Set([...i(e), ...i(t)]), a = /* @__PURE__ */ new Map();
13
+ return i(t).forEach((s) => {
14
+ if (Object.values(t).find((e) => Object.hasOwn(e, s))?.[s]?.type === "element" || !i(e).has(s) || r(s, e, t)) return;
15
+ let c = o(s, n);
16
+ n.add(c), a.set(s, c);
17
+ }), a;
18
+ }, c = (e, t, n) => {
19
+ let r = t !== e.name, i = Object.fromEntries(Object.entries(e.attributes).map(([e, t]) => {
20
+ if (!t.ancestors || !Object.keys(t.ancestors).some((e) => n.has(e))) return [e, t];
21
+ r = !0;
22
+ let i = Object.fromEntries(Object.entries(t.ancestors).map(([e, t]) => [n.get(e) ?? e, t]));
23
+ return [e, {
24
+ ...t,
25
+ ancestors: i
26
+ }];
27
+ }));
28
+ if (!r) return e;
29
+ let o = {
30
+ ...e,
31
+ name: t,
32
+ attributes: i
33
+ };
34
+ return {
35
+ ...o,
36
+ cache: a(o)
37
+ };
38
+ }, l = (e, t) => {
39
+ if (t.size === 0) return e;
40
+ let r = { ...e.platform };
41
+ return Object.keys(r).filter(n).forEach((e) => {
42
+ r[e] = Object.fromEntries(Object.entries(r[e]).map(([e, n]) => {
43
+ let r = t.get(e) ?? e;
44
+ return [r, c(n, r, t)];
45
+ }));
46
+ }), {
47
+ ...e,
48
+ platform: r
49
+ };
50
+ }, u = (e, t) => {
51
+ Object.values(e).forEach((e) => {
52
+ let { styleSelectors: n } = e.definition;
53
+ Object.keys(n).forEach((e) => {
54
+ n[e] = n[e].split(/\s+/).map((e) => t.get(e) ?? e).join(" ");
55
+ });
56
+ });
57
+ }, d = (n, r) => {
58
+ let i = structuredClone({
59
+ ...r.initialItems,
60
+ [r.data.id]: r.data
61
+ }), a = t(n.schema), o = e(i, (e) => a.has(e)), c = r.style ? s(n.style.platform, r.style.platform) : /* @__PURE__ */ new Map();
62
+ u(i, c);
63
+ let { [o[r.data.id] ?? r.data.id]: d, ...f } = i;
64
+ return {
65
+ data: d,
66
+ initialItems: f,
67
+ style: r.style && l(r.style, c)
68
+ };
69
+ };
70
+ //#endregion
71
+ export { d as default };
@@ -1,5 +1,6 @@
1
1
  import { Schema } from '@plitzi/sdk-shared';
2
2
  export type SchemaValidationOptions = {
3
+ /** Validates `flat` as a fragment hung off this element — a component's tree — instead of as the pages' tree. */
3
4
  baseElementId?: string;
4
5
  /**
5
6
  * Element type → the source name it publishes under.
@@ -14,6 +15,8 @@ export type SchemaValidationError = {
14
15
  code: string;
15
16
  message: string;
16
17
  elementId?: string;
18
+ /** The component whose tree the error is in; absent for the pages' tree. */
19
+ componentId?: string;
17
20
  details?: unknown;
18
21
  };
19
22
  export type SchemaValidationResult = {