@septkit/ui 0.0.48 → 0.0.50

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 (21) hide show
  1. package/dist/dialecte/composables/use-active-document.js +18 -11
  2. package/dist/dialecte/create-document-store.js +3 -3
  3. package/dist/external/.pnpm/{@dialecte_core@0.4.7 → @dialecte_core@0.4.9}/node_modules/@dialecte/core/dist/helpers.js +16 -19
  4. package/dist/external/.pnpm/{@dialecte_core@0.4.7 → @dialecte_core@0.4.9}/node_modules/@dialecte/core/dist/index.js +1 -1
  5. package/dist/external/.pnpm/{@dialecte_core@0.4.7/node_modules/@dialecte/core/dist/project-DxIu-3AU.js → @dialecte_core@0.4.9/node_modules/@dialecte/core/dist/project-D-KS3OPN.js} +1 -1
  6. package/dist/external/.pnpm/{@dialecte_core@0.4.7 → @dialecte_core@0.4.9}/node_modules/@dialecte/core/dist/utils-C5_11hqg.js +1 -1
  7. package/dist/external/.pnpm/{@dialecte_scl@0.3.8/node_modules/@dialecte/scl/dist/hooks-DJJN-WU2.js → @dialecte_scl@0.3.9/node_modules/@dialecte/scl/dist/hooks-DO4gUiix.js} +48 -5277
  8. package/dist/external/.pnpm/@dialecte_scl@0.3.9/node_modules/@dialecte/scl/dist/v2019C1/index.js +3 -0
  9. package/dist/external/.pnpm/@lucide_vue@1.23.0_vue@3.5.39_typescript@5.8.3_/node_modules/@lucide/vue/dist/esm/icons/rotate-ccw.js +11 -0
  10. package/dist/index.d.ts +27 -1
  11. package/dist/merge/affix.js +14 -0
  12. package/dist/merge/build-view-model.js +37 -21
  13. package/dist/merge/element-detail.vue_vue_type_script_setup_true_lang.js +93 -32
  14. package/dist/merge/merge-review.vue_vue_type_script_setup_true_lang.js +159 -152
  15. package/dist/merge/merge-summary.vue_vue_type_script_setup_true_lang.js +47 -25
  16. package/dist/merge/merge-tree.vue_vue_type_script_setup_true_lang.js +11 -9
  17. package/dist/merge/merge.service.js +2 -2
  18. package/dist/merge/use-merge-session.js +4 -1
  19. package/dist/ui.css +1 -1
  20. package/package.json +3 -3
  21. package/dist/external/.pnpm/@dialecte_scl@0.3.8/node_modules/@dialecte/scl/dist/v2019C1/index.js +0 -3
@@ -0,0 +1,3 @@
1
+ import "../../../../../../@dialecte_core@0.4.9/node_modules/@dialecte/core/dist/index.js";
2
+ import { i as e } from "../hooks-DO4gUiix.js";
3
+ export { e as presentationScope };
@@ -0,0 +1,11 @@
1
+ import e from "../createLucideIcon.js";
2
+ //#region node_modules/.pnpm/@lucide+vue@1.23.0_vue@3.5.39_typescript@5.8.3_/node_modules/@lucide/vue/dist/esm/icons/rotate-ccw.mjs
3
+ var t = [["path", {
4
+ d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8",
5
+ key: "1357e3"
6
+ }], ["path", {
7
+ d: "M3 3v5h5",
8
+ key: "1xhq8a"
9
+ }]], n = e("rotate-ccw", t);
10
+ //#endregion
11
+ export { t as __iconNode, n as default };
package/dist/index.d.ts CHANGED
@@ -98,11 +98,14 @@ declare type __VLS_Props_10 = {
98
98
 
99
99
  declare type __VLS_Props_11 = {
100
100
  detail: ElementDetailVM | undefined;
101
+ /** Consumer-supplied fixed prefix/suffix per attribute; the user edits only the core. */
102
+ affixMask?: AffixMaskResolver;
101
103
  };
102
104
 
103
105
  declare type __VLS_Props_12 = MergeSessionParams & {
104
106
  source?: FileMeta;
105
107
  target?: FileMeta;
108
+ affixMask?: AffixMaskResolver;
106
109
  };
107
110
 
108
111
  declare type __VLS_Props_13 = {
@@ -364,6 +367,12 @@ export declare type ActiveFeedback = {
364
367
  variant: FeedbackVariant;
365
368
  } & FeedbackPayload;
366
369
 
370
+ /** Resolves the affix (if any) for a given element tag + attribute name. Consumer-supplied. */
371
+ export declare type AffixMaskResolver = (params: {
372
+ tag: string;
373
+ attr: string;
374
+ }) => AttributeAffix | undefined;
375
+
367
376
  /**
368
377
  * Consumer hook run INSIDE the merge transaction, right after `tx.lifecycle.apply`.
369
378
  * Receives the `ApplyResult` (the instance roots the write produced) so a caller can
@@ -380,12 +389,23 @@ declare type AfterApplyContext = {
380
389
  result: ApplyResult;
381
390
  };
382
391
 
392
+ /**
393
+ * A fixed prefix/suffix wrapped around an editable attribute value. The user edits only
394
+ * the "core" between them; the affix is rendered as inert adornment and re-applied on
395
+ * commit. Lets a consumer keep a convention marker (e.g. SET's `_App`) out of the user's
396
+ * reach without the generic component knowing what the marker means.
397
+ */
398
+ export declare type AttributeAffix = {
399
+ prefix?: string;
400
+ suffix?: string;
401
+ };
402
+
383
403
  export declare const Button: __VLS_WithTemplateSlots<typeof __VLS_component, __VLS_TemplateResult["slots"]>;
384
404
 
385
405
  export declare const CATEGORY_ELEMENTS: Record<string, string[]>;
386
406
 
387
407
  /** How an element or attribute changed between the template and the instance. */
388
- export declare type ChangeStatus = 'added' | 'removed' | 'modified' | 'unchanged';
408
+ export declare type ChangeStatus = 'added' | 'removed' | 'modified' | 'unchanged' | 'target-only';
389
409
 
390
410
  declare function closeDropdown(): void;
391
411
 
@@ -636,6 +656,12 @@ export declare type MergeNodeMeta = {
636
656
  role: 'primary' | 'companion' | 'plain';
637
657
  /** The decision group this node belongs to (primary + companions share it). */
638
658
  groupId?: string;
659
+ /**
660
+ * The topmost changed node of a change region (no changed same-group ancestor above it).
661
+ * Only region heads carry a status marker, so one badge shows per change instead of
662
+ * scattering across correlated companions but not their uuid-less siblings.
663
+ */
664
+ regionHead?: boolean;
639
665
  /** For a satellite companion that lives elsewhere: its real document path (shown as subtitle). */
640
666
  path?: string;
641
667
  };
@@ -0,0 +1,14 @@
1
+ //#region lib/merge/affix.ts
2
+ function e(e, t) {
3
+ let n = t?.prefix ?? "", r = t?.suffix ?? "", i = e;
4
+ return n && i.startsWith(n) && (i = i.slice(n.length)), r && i.endsWith(r) && (i = i.slice(0, i.length - r.length)), {
5
+ prefix: n,
6
+ core: i,
7
+ suffix: r
8
+ };
9
+ }
10
+ function t(e, t) {
11
+ return `${t?.prefix ?? ""}${e}${t?.suffix ?? ""}`;
12
+ }
13
+ //#endregion
14
+ export { t as composeAffix, e as splitAffix };
@@ -47,41 +47,45 @@ async function r(t) {
47
47
  index: {},
48
48
  expanded: []
49
49
  };
50
- async function o(t, n) {
51
- let s = r.get(t.id), c = s?.change ?? (n.added ? "added" : "unchanged"), l = s?.groupId ?? (c === "unchanged" ? void 0 : n.groupId), u = s?.role ?? "plain", d = {
50
+ async function o(t, n, s) {
51
+ let c = r.get(t.id), l = c?.change ?? (n.added ? "added" : "unchanged"), u = c?.groupId ?? (l === "unchanged" ? void 0 : n.groupId), d = c?.role ?? "plain", f = {
52
52
  tagName: t.tagName,
53
53
  id: t.id
54
- }, f = {
55
- added: s ? s.change === "added" : n.added,
56
- groupId: l ?? n.groupId
57
- }, p = [];
58
- for (let e of t.tree ?? []) p.push(await o(e, f));
59
- let m = c !== "unchanged" || p.some((e) => e.changed);
54
+ }, p = l !== "unchanged" && (!s || s.change === "unchanged" || s.groupId !== u), m = {
55
+ added: c ? c.change === "added" : n.added,
56
+ groupId: u ?? n.groupId
57
+ }, h = [];
58
+ for (let e of t.tree ?? []) h.push(await o(e, m, {
59
+ change: l,
60
+ groupId: u
61
+ }));
62
+ let g = l !== "unchanged" || h.some((e) => e.changed);
60
63
  return a.meta[t.id] = {
61
- change: c,
62
- role: u,
63
- groupId: l
64
+ change: l,
65
+ role: d,
66
+ groupId: u,
67
+ regionHead: p
64
68
  }, a.index[t.id] = {
65
- previewRef: d,
66
- change: c,
67
- role: u,
68
- groupId: l,
69
- node: s?.node
70
- }, m && a.expanded.push(t.id), {
69
+ previewRef: f,
70
+ change: l,
71
+ role: d,
72
+ groupId: u,
73
+ node: c?.node
74
+ }, g && a.expanded.push(t.id), {
71
75
  node: {
72
76
  tag: t.tagName,
73
77
  id: t.id,
74
- name: await e(i, d),
78
+ name: await e(i, f),
75
79
  selectable: !0,
76
- children: p.length ? p.map((e) => e.node) : void 0
80
+ children: h.length ? h.map((e) => e.node) : void 0
77
81
  },
78
- changed: m
82
+ changed: g
79
83
  };
80
84
  }
81
85
  return a.items.push((await o(n, {
82
86
  added: !1,
83
87
  groupId: void 0
84
- })).node), a;
88
+ }, void 0)).node), a;
85
89
  }
86
90
  async function i(e, n, r) {
87
91
  let i = new Map((n?.editableAttributes ?? []).map((e) => [e.attr, e])), a = [];
@@ -148,10 +152,22 @@ async function a(e, t, n, r) {
148
152
  added: [],
149
153
  updated: [],
150
154
  skipped: [],
155
+ preserved: [],
156
+ removed: [],
151
157
  renamed: []
152
158
  };
153
159
  for (let a of e.groups) {
154
160
  let e = await o(a.primary, r), s = a.primary.tagName, c = a.companions.length;
161
+ if (a.primary.change === "target-only") {
162
+ t(a.id) === "skip" ? i.preserved.push({
163
+ title: e,
164
+ tag: s
165
+ }) : i.removed.push({
166
+ title: e,
167
+ tag: s
168
+ });
169
+ continue;
170
+ }
155
171
  if (t(a.id) === "skip") {
156
172
  i.skipped.push({
157
173
  title: e,
@@ -1,52 +1,113 @@
1
- import { Fragment as e, computed as t, createCommentVNode as n, createElementBlock as r, createElementVNode as i, defineComponent as a, normalizeClass as o, openBlock as s, renderList as c, toDisplayString as l } from "vue";
1
+ import e from "../external/.pnpm/@lucide_vue@1.23.0_vue@3.5.39_typescript@5.8.3_/node_modules/@lucide/vue/dist/esm/icons/rotate-ccw.js";
2
+ import { composeAffix as t, splitAffix as n } from "./affix.js";
3
+ import { Fragment as r, computed as i, createCommentVNode as a, createElementBlock as o, createElementVNode as s, createVNode as c, defineComponent as l, normalizeClass as u, openBlock as d, renderList as f, toDisplayString as p, unref as m } from "vue";
2
4
  //#region lib/merge/element-detail.vue?vue&type=script&setup=true&lang.ts
3
- var u = {
5
+ var h = {
4
6
  key: 0,
5
7
  class: "flex h-full flex-col gap-3 overflow-auto p-3 text-sm"
6
- }, d = { class: "flex items-center gap-2" }, f = { class: "font-medium" }, p = { class: "badge badge-sm opacity-70" }, m = {
8
+ }, g = { class: "flex items-center gap-2" }, _ = { class: "font-medium" }, v = { class: "badge badge-sm opacity-70" }, y = {
7
9
  key: 0,
8
- class: "flex flex-col gap-2 font-mono text-xs"
9
- }, h = { class: "whitespace-nowrap shrink-0 opacity-70" }, g = ["value", "onInput"], _ = {
10
+ class: "flex flex-col gap-2 text-xs"
11
+ }, b = { class: "flex items-center gap-2" }, x = ["title"], S = { class: "flex w-full items-center font-mono" }, C = {
10
12
  key: 0,
13
+ class: "shrink-0 select-none opacity-60"
14
+ }, w = ["value", "onInput"], T = {
15
+ key: 1,
16
+ class: "shrink-0 select-none opacity-60"
17
+ }, E = [
18
+ "title",
19
+ "aria-pressed",
20
+ "onClick"
21
+ ], D = {
22
+ key: 1,
11
23
  class: "badge badge-warning badge-xs shrink-0",
12
24
  title: "Auto-resolved to avoid a naming collision — edit to override"
13
- }, v = {
25
+ }, O = {
26
+ key: 0,
27
+ class: "mt-1 flex items-center gap-1 pl-24 font-mono opacity-70"
28
+ }, k = { class: "line-through decoration-error/60" }, A = { class: "text-warning" }, j = {
29
+ key: 1,
30
+ class: "badge badge-info badge-xs"
31
+ }, M = {
14
32
  key: 1,
15
33
  class: "text-xs opacity-60"
16
- }, y = {
34
+ }, N = {
17
35
  key: 1,
18
36
  class: "grid h-full place-items-center p-4 text-sm opacity-60"
19
- }, b = /*@__PURE__*/ a({
37
+ }, P = /*@__PURE__*/ l({
20
38
  __name: "element-detail",
21
- props: { detail: {} },
39
+ props: {
40
+ detail: {},
41
+ affixMask: { type: Function }
42
+ },
22
43
  emits: ["edit"],
23
- setup(a, { emit: b }) {
24
- let x = a, S = b, C = t(() => ({
44
+ setup(l, { emit: P }) {
45
+ let F = l, I = P, L = i(() => ({
25
46
  added: "badge-success",
26
47
  removed: "badge-error",
27
48
  modified: "badge-warning",
28
- unchanged: "badge-ghost"
29
- })[x.detail?.change ?? "unchanged"]), w = t(() => x.detail?.attributes.filter((e) => e.editable));
30
- function T(e, t) {
31
- S("edit", e.name, t.target.value);
49
+ unchanged: "badge-ghost",
50
+ "target-only": "badge-info"
51
+ })[F.detail?.change ?? "unchanged"]), R = i(() => [...F.detail?.attributes ?? []].filter((e) => e.editable).sort((e, t) => Number(V(t)) - Number(V(e))));
52
+ function z(e) {
53
+ if (!(!F.detail || !F.affixMask)) return F.affixMask({
54
+ tag: F.detail.tag,
55
+ attr: e.name
56
+ });
57
+ }
58
+ function B(e) {
59
+ return n(e.after ?? "", z(e));
60
+ }
61
+ function V(e) {
62
+ return e.status === "modified";
63
+ }
64
+ function H(e) {
65
+ return V(e) && (e.after ?? "") === (e.before ?? "");
66
+ }
67
+ function U(e, n) {
68
+ let r = n.target.value;
69
+ I("edit", e.name, t(r, z(e)));
70
+ }
71
+ function W(e) {
72
+ I("edit", e.name, e.before ?? "");
32
73
  }
33
- return (t, b) => a.detail ? (s(), r("div", u, [i("header", d, [
34
- i("span", f, l(a.detail.title), 1),
35
- i("span", p, l(a.detail.tag), 1),
36
- i("span", { class: o(["badge badge-sm", C.value]) }, l(a.detail.change), 3)
37
- ]), w.value?.length ? (s(), r("div", m, [(s(!0), r(e, null, c(w.value, (e) => (s(), r("label", {
38
- key: e.name,
39
- class: "flex items-center gap-2"
40
- }, [
41
- i("span", h, l(e.name) + ":", 1),
42
- i("input", {
43
- class: o(["input input-xs input-bordered w-full font-mono", { "input-warning": e.conflict }]),
44
- value: e.after ?? "",
45
- onInput: (t) => T(e, t)
46
- }, null, 42, g),
47
- e.conflict ? (s(), r("span", _, " conflict ")) : n("", !0)
48
- ]))), 128))])) : (s(), r("div", v, "No editable fields. See the diff below."))])) : (s(), r("div", y, " Select an element to see its changes. "));
74
+ return (t, n) => l.detail ? (d(), o("div", h, [s("header", g, [
75
+ s("span", _, p(l.detail.title), 1),
76
+ s("span", v, p(l.detail.tag), 1),
77
+ s("span", { class: u(["badge badge-sm", L.value]) }, p(l.detail.change), 3)
78
+ ]), R.value.length ? (d(), o("div", y, [(d(!0), o(r, null, f(R.value, (t) => (d(), o("div", {
79
+ key: t.name,
80
+ class: u(["rounded-md border px-2 py-1.5", V(t) ? "border-warning/40 bg-warning/5" : "border-base-200"])
81
+ }, [s("div", b, [
82
+ s("span", {
83
+ class: "w-24 shrink-0 truncate opacity-70",
84
+ title: t.name
85
+ }, p(t.name), 9, x),
86
+ s("span", S, [
87
+ B(t).prefix ? (d(), o("span", C, p(B(t).prefix), 1)) : a("", !0),
88
+ s("input", {
89
+ class: u(["input input-xs input-bordered w-full font-mono", { "input-warning": t.conflict }]),
90
+ value: B(t).core,
91
+ onInput: (e) => U(t, e)
92
+ }, null, 42, w),
93
+ B(t).suffix ? (d(), o("span", T, p(B(t).suffix), 1)) : a("", !0)
94
+ ]),
95
+ V(t) ? (d(), o("button", {
96
+ key: 0,
97
+ type: "button",
98
+ class: u(["btn btn-ghost btn-xs btn-square shrink-0", H(t) ? "text-info" : "opacity-60 hover:opacity-100"]),
99
+ title: H(t) ? "Keeping the current value — click again is a no-op" : `Keep current value: ${t.before || "(empty)"}`,
100
+ "aria-pressed": H(t),
101
+ "aria-label": "Keep current value",
102
+ onClick: (e) => W(t)
103
+ }, [c(m(e), { class: "size-3.5" })], 10, E)) : a("", !0),
104
+ t.conflict ? (d(), o("span", D, " conflict ")) : a("", !0)
105
+ ]), V(t) ? (d(), o("p", O, [
106
+ n[1] ||= s("span", { class: "opacity-60" }, "current", -1),
107
+ s("span", k, p(t.before || "∅"), 1),
108
+ H(t) ? (d(), o("span", j, "kept")) : (d(), o(r, { key: 0 }, [n[0] ||= s("span", { class: "opacity-50" }, "→", -1), s("span", A, p(t.after || "∅"), 1)], 64))
109
+ ])) : a("", !0)], 2))), 128))])) : (d(), o("div", M, "No editable fields. See the diff below."))])) : (d(), o("div", N, " Select an element to see its changes. "));
49
110
  }
50
111
  });
51
112
  //#endregion
52
- export { b as default };
113
+ export { P as default };