@kopexa/extension-controlref 1.0.0 → 13.0.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.
Files changed (126) hide show
  1. package/dist/chunk-4C72VBLP.mjs +52 -0
  2. package/dist/chunk-A7FWOQDN.mjs +210 -0
  3. package/dist/chunk-AQTNFDGA.mjs +57 -0
  4. package/dist/chunk-D53W4HWR.mjs +245 -0
  5. package/dist/chunk-FTEE5U3H.mjs +37 -0
  6. package/dist/chunk-GYDJVHHG.mjs +250 -0
  7. package/dist/chunk-IMHLTRZJ.mjs +29 -0
  8. package/dist/chunk-JM66CQVD.mjs +10 -0
  9. package/dist/chunk-LMKP3DDN.mjs +189 -0
  10. package/dist/chunk-RTBFRPB3.mjs +186 -0
  11. package/dist/chunk-TEDXYIGO.mjs +38 -0
  12. package/dist/chunk-WIS7ZNTO.mjs +4 -0
  13. package/dist/chunk-X46EFFCE.mjs +148 -0
  14. package/dist/chunk-XHD2KFKQ.mjs +16 -0
  15. package/dist/chunk-ZRKYAFRY.mjs +46 -0
  16. package/dist/chunk-ZUR6XKMG.mjs +21 -0
  17. package/dist/components/control-block-view.d.mts +6 -0
  18. package/dist/components/control-block-view.d.ts +6 -0
  19. package/dist/components/control-block-view.js +789 -0
  20. package/dist/components/control-block-view.mjs +11 -0
  21. package/dist/components/control-implementation-view.d.mts +6 -0
  22. package/dist/components/control-implementation-view.d.ts +6 -0
  23. package/dist/components/control-implementation-view.js +52 -0
  24. package/dist/components/control-implementation-view.mjs +7 -0
  25. package/dist/components/control-picker.d.mts +25 -0
  26. package/dist/components/control-picker.d.ts +25 -0
  27. package/dist/components/control-picker.js +522 -0
  28. package/dist/components/control-picker.mjs +10 -0
  29. package/dist/components/control-view.js +677 -122
  30. package/dist/components/control-view.mjs +5 -5
  31. package/dist/components/use-control.d.mts +20 -0
  32. package/dist/components/use-control.d.ts +20 -0
  33. package/dist/components/use-control.js +127 -0
  34. package/dist/components/use-control.mjs +9 -0
  35. package/dist/control-block.d.mts +35 -0
  36. package/dist/control-block.d.ts +35 -0
  37. package/dist/control-block.js +1012 -0
  38. package/dist/control-block.mjs +17 -0
  39. package/dist/control-implementation.d.mts +7 -0
  40. package/dist/control-implementation.d.ts +7 -0
  41. package/dist/control-implementation.js +92 -0
  42. package/dist/control-implementation.mjs +9 -0
  43. package/dist/control.d.mts +31 -1
  44. package/dist/control.d.ts +31 -1
  45. package/dist/control.js +819 -136
  46. package/dist/control.mjs +7 -6
  47. package/dist/defaults.d.mts +3 -9
  48. package/dist/defaults.d.ts +3 -9
  49. package/dist/defaults.js +3 -20
  50. package/dist/defaults.mjs +3 -6
  51. package/dist/index.d.mts +10 -10
  52. package/dist/index.d.ts +10 -10
  53. package/dist/index.js +1229 -569
  54. package/dist/index.mjs +58 -21
  55. package/dist/messages/index.d.mts +135 -0
  56. package/dist/messages/index.d.ts +135 -0
  57. package/dist/messages/index.js +137 -2
  58. package/dist/messages/index.mjs +1 -2
  59. package/dist/role.d.mts +17 -0
  60. package/dist/role.d.ts +17 -0
  61. package/dist/role.js +5 -0
  62. package/dist/role.mjs +2 -0
  63. package/dist/types.d.mts +23 -16
  64. package/dist/types.d.ts +23 -16
  65. package/dist/utils/create-control-block.d.mts +7 -0
  66. package/dist/utils/create-control-block.d.ts +7 -0
  67. package/dist/utils/create-control-block.js +85 -0
  68. package/dist/utils/create-control-block.mjs +10 -0
  69. package/dist/utils/create-control-implementation.d.mts +8 -0
  70. package/dist/utils/create-control-implementation.d.ts +8 -0
  71. package/dist/utils/create-control-implementation.js +39 -0
  72. package/dist/utils/create-control-implementation.mjs +7 -0
  73. package/dist/utils/getControlNodeTypes.d.mts +5 -0
  74. package/dist/utils/getControlNodeTypes.d.ts +5 -0
  75. package/dist/utils/getControlNodeTypes.js +44 -0
  76. package/dist/utils/getControlNodeTypes.mjs +7 -0
  77. package/dist/utils/index.d.mts +7 -2
  78. package/dist/utils/index.d.ts +7 -2
  79. package/dist/utils/index.js +35 -3
  80. package/dist/utils/index.mjs +7 -4
  81. package/dist/utils/status-indicator.d.mts +18 -0
  82. package/dist/utils/status-indicator.d.ts +18 -0
  83. package/dist/utils/status-indicator.js +80 -0
  84. package/dist/utils/status-indicator.mjs +7 -0
  85. package/package.json +11 -11
  86. package/dist/card-variant.d.mts +0 -12
  87. package/dist/card-variant.d.ts +0 -12
  88. package/dist/card-variant.js +0 -66
  89. package/dist/card-variant.mjs +0 -8
  90. package/dist/chunk-AC4KL3WX.mjs +0 -29
  91. package/dist/chunk-AZ5M5MVC.mjs +0 -36
  92. package/dist/chunk-DTFR234X.mjs +0 -244
  93. package/dist/chunk-EDD7DYLE.mjs +0 -29
  94. package/dist/chunk-GC5EBQ7G.mjs +0 -10
  95. package/dist/chunk-H2ECPGOG.mjs +0 -81
  96. package/dist/chunk-KLX7Q3HL.mjs +0 -109
  97. package/dist/chunk-LKRTUIEV.mjs +0 -46
  98. package/dist/chunk-NAJ6IC4Y.mjs +0 -43
  99. package/dist/chunk-QI3ZPZTR.mjs +0 -26
  100. package/dist/chunk-SNRVOTF5.mjs +0 -8
  101. package/dist/chunk-VP5POY44.mjs +0 -57
  102. package/dist/chunk-WIR5FCIC.mjs +0 -110
  103. package/dist/control-ref-view.d.mts +0 -6
  104. package/dist/control-ref-view.d.ts +0 -6
  105. package/dist/control-ref-view.js +0 -615
  106. package/dist/control-ref-view.mjs +0 -15
  107. package/dist/control-ref.d.mts +0 -28
  108. package/dist/control-ref.d.ts +0 -28
  109. package/dist/control-ref.js +0 -687
  110. package/dist/control-ref.mjs +0 -16
  111. package/dist/i18n.d.mts +0 -4
  112. package/dist/i18n.d.ts +0 -4
  113. package/dist/i18n.js +0 -128
  114. package/dist/i18n.mjs +0 -10
  115. package/dist/lang/de.d.mts +0 -24
  116. package/dist/lang/de.d.ts +0 -24
  117. package/dist/lang/de.js +0 -25
  118. package/dist/lang/de.mjs +0 -8
  119. package/dist/lang/en.d.mts +0 -24
  120. package/dist/lang/en.d.ts +0 -24
  121. package/dist/lang/en.js +0 -25
  122. package/dist/lang/en.mjs +0 -8
  123. package/dist/settings-dialog.d.mts +0 -19
  124. package/dist/settings-dialog.d.ts +0 -19
  125. package/dist/settings-dialog.js +0 -371
  126. package/dist/settings-dialog.mjs +0 -9
@@ -0,0 +1,250 @@
1
+ "use client";
2
+ import {
3
+ ControlPicker
4
+ } from "./chunk-A7FWOQDN.mjs";
5
+ import {
6
+ useControl
7
+ } from "./chunk-4C72VBLP.mjs";
8
+ import {
9
+ messages
10
+ } from "./chunk-D53W4HWR.mjs";
11
+
12
+ // src/components/control-block-view.tsx
13
+ import { useSafeIntl } from "@kopexa/i18n";
14
+ import { SettingsIcon } from "@kopexa/icons";
15
+ import {
16
+ Button,
17
+ Callout,
18
+ Card,
19
+ Chip,
20
+ Dialog,
21
+ Heading,
22
+ IconButton,
23
+ Label,
24
+ Select,
25
+ Switch
26
+ } from "@kopexa/sight";
27
+ import {
28
+ NodeViewContent,
29
+ NodeViewWrapper
30
+ } from "@tiptap/react";
31
+ import { useState } from "react";
32
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
33
+ var ControlBlockView = (props) => {
34
+ var _a, _b, _c, _d, _e, _f;
35
+ const { node, editor, updateAttributes, getPos } = props;
36
+ const attrs = node.attrs;
37
+ const { showStatus, variant } = attrs.options || {};
38
+ const resolver = props.extension.options.resolver;
39
+ const intl = useSafeIntl();
40
+ const { interactive, ind, mapped, isMissing, isOutdated } = useControl({
41
+ attrs,
42
+ resolver,
43
+ editor
44
+ });
45
+ return /* @__PURE__ */ jsx(NodeViewWrapper, { "data-id": (_a = attrs.id) != null ? _a : "", children: /* @__PURE__ */ jsxs(Card.Root, { variant, children: [
46
+ /* @__PURE__ */ jsxs(Card.Header, { children: [
47
+ /* @__PURE__ */ jsx(Card.Heading, { children: /* @__PURE__ */ jsx(Heading, { level: "h3", contentEditable: false, children: (_b = attrs.title) != null ? _b : "Unmapped Control" }) }),
48
+ /* @__PURE__ */ jsxs(Card.Toolbar, { children: [
49
+ showStatus && /* @__PURE__ */ jsx(
50
+ Chip,
51
+ {
52
+ size: "sm",
53
+ "data-active": open,
54
+ contentEditable: false,
55
+ indicator: ind.indicator,
56
+ indicatorColor: ind.indicatorColor,
57
+ indicatorVariant: ind.indicatorVariant,
58
+ ...((_c = attrs.options) == null ? void 0 : _c.showStatus) && (attrs == null ? void 0 : attrs.status) && { status: attrs.status },
59
+ variant: "bordered",
60
+ children: (_d = attrs.title) != null ? _d : "Unmapped Control"
61
+ }
62
+ ),
63
+ interactive && /* @__PURE__ */ jsx(
64
+ SettingsDialog,
65
+ {
66
+ resolver,
67
+ initialSelection: attrs.id ? {
68
+ id: attrs.id,
69
+ title: (_e = attrs.title) != null ? _e : "",
70
+ status: (_f = attrs.status) != null ? _f : null
71
+ } : null,
72
+ initialOptions: attrs.options,
73
+ onSave: async ({ control, options }) => {
74
+ var _a2, _b2, _c2, _d2;
75
+ updateAttributes({
76
+ id: (_a2 = control == null ? void 0 : control.id) != null ? _a2 : null,
77
+ title: (_b2 = control == null ? void 0 : control.title) != null ? _b2 : null,
78
+ status: (_c2 = control == null ? void 0 : control.status) != null ? _c2 : null,
79
+ updatedAt: control == null ? void 0 : control.updatedAt,
80
+ options
81
+ });
82
+ const pos = typeof getPos === "function" ? getPos() : null;
83
+ if (pos == null) return;
84
+ const rows = (_d2 = control == null ? void 0 : control.implementations) != null ? _d2 : [];
85
+ try {
86
+ editor.commands.setControlImplementationsAt(pos, rows);
87
+ } catch {
88
+ editor.commands.setControlImplementationsAt(pos, []);
89
+ }
90
+ },
91
+ onUnlink: () => {
92
+ updateAttributes({ id: null, title: null, status: null });
93
+ const pos = typeof getPos === "function" ? getPos() : null;
94
+ if (pos != null)
95
+ editor.commands.setControlImplementationsAt(pos, []);
96
+ }
97
+ }
98
+ )
99
+ ] })
100
+ ] }),
101
+ /* @__PURE__ */ jsxs(Card.Body, { children: [
102
+ interactive && /* @__PURE__ */ jsxs(Fragment, { children: [
103
+ mapped && isMissing && /* @__PURE__ */ jsx(
104
+ Callout,
105
+ {
106
+ print: false,
107
+ variant: "destructive",
108
+ contentEditable: false,
109
+ className: "mb-4",
110
+ children: intl.formatMessage(messages.missing_callout)
111
+ }
112
+ ),
113
+ !isMissing && isOutdated && /* @__PURE__ */ jsx(
114
+ Callout,
115
+ {
116
+ print: false,
117
+ variant: "warning",
118
+ contentEditable: false,
119
+ className: "mb-4",
120
+ children: intl.formatMessage(messages.outdated_callout)
121
+ }
122
+ )
123
+ ] }),
124
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3", children: /* @__PURE__ */ jsx(NodeViewContent, { className: "content is-editable", as: "div" }) })
125
+ ] })
126
+ ] }) });
127
+ };
128
+ var SettingsDialog = ({
129
+ initialSelection,
130
+ initialOptions,
131
+ resolver,
132
+ onSave
133
+ }) => {
134
+ const intl = useSafeIntl();
135
+ const [isOpen, onOpenChange] = useState(false);
136
+ const [selection, setSelection] = useState(
137
+ initialSelection
138
+ );
139
+ const [options, setOptions] = useState({
140
+ showStatus: false,
141
+ ...initialOptions
142
+ });
143
+ return /* @__PURE__ */ jsxs(Dialog, { size: "2xl", open: isOpen, onOpenChange, children: [
144
+ /* @__PURE__ */ jsx(
145
+ Dialog.Trigger,
146
+ {
147
+ render: /* @__PURE__ */ jsx(IconButton, { variant: "outline", color: "default", "aria-label": "Settings", children: /* @__PURE__ */ jsx(SettingsIcon, {}) })
148
+ }
149
+ ),
150
+ /* @__PURE__ */ jsxs(Dialog.Content, { children: [
151
+ /* @__PURE__ */ jsxs(Dialog.Header, { children: [
152
+ /* @__PURE__ */ jsx(Dialog.Title, { children: (selection == null ? void 0 : selection.title) ? intl.formatMessage(messages.control_with_title, {
153
+ title: selection.title
154
+ }) : intl.formatMessage(messages.map_control) }),
155
+ /* @__PURE__ */ jsx(Dialog.Description, { children: intl.formatMessage(messages.settings_dialog_description) })
156
+ ] }),
157
+ /* @__PURE__ */ jsxs(Dialog.Body, { children: [
158
+ /* @__PURE__ */ jsx(
159
+ ControlPicker,
160
+ {
161
+ resolver,
162
+ value: selection,
163
+ onChange: (next) => {
164
+ setSelection(next);
165
+ },
166
+ debounceMs: 300,
167
+ timeoutMs: 5e3
168
+ }
169
+ ),
170
+ /* @__PURE__ */ jsxs("div", { className: "mt-6 flex flex-col gap-3", children: [
171
+ /* @__PURE__ */ jsx(Label, { children: intl.formatMessage(messages.display_options) }),
172
+ /* @__PURE__ */ jsxs(
173
+ Label,
174
+ {
175
+ variant: "secondary",
176
+ className: "flex items-center justify-between gap-3",
177
+ children: [
178
+ /* @__PURE__ */ jsx("span", { children: intl.formatMessage(messages.header_status) }),
179
+ /* @__PURE__ */ jsx(
180
+ Switch,
181
+ {
182
+ "aria-label": intl.formatMessage(messages.header_status_aria),
183
+ checked: !!options.showStatus,
184
+ onCheckedChange: (checked) => setOptions((o) => ({ ...o, showStatus: checked }))
185
+ }
186
+ )
187
+ ]
188
+ }
189
+ ),
190
+ /* @__PURE__ */ jsx(Callout, { variant: "info", children: intl.formatMessage(messages.header_status_avv_tip) }),
191
+ /* @__PURE__ */ jsxs(
192
+ Label,
193
+ {
194
+ variant: "secondary",
195
+ className: "flex items-center justify-between gap-3",
196
+ children: [
197
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
198
+ /* @__PURE__ */ jsx("span", { children: intl.formatMessage(messages.variant) }),
199
+ /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm", children: intl.formatMessage(messages.variant_hint) })
200
+ ] }),
201
+ /* @__PURE__ */ jsxs(
202
+ Select,
203
+ {
204
+ value: options.variant || "default",
205
+ onValueChange: (value) => setOptions((o) => ({
206
+ ...o,
207
+ variant: value
208
+ })),
209
+ children: [
210
+ /* @__PURE__ */ jsx(Select.Trigger, { className: "w-[180px]", children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Select a variant" }) }),
211
+ /* @__PURE__ */ jsxs(Select.Content, { children: [
212
+ /* @__PURE__ */ jsx(Select.Item, { value: "default", children: "Default" }),
213
+ /* @__PURE__ */ jsx(Select.Item, { value: "muted", children: "Muted" }),
214
+ /* @__PURE__ */ jsx(Select.Item, { value: "accent", children: "Accent" })
215
+ ] })
216
+ ]
217
+ }
218
+ )
219
+ ]
220
+ }
221
+ )
222
+ ] })
223
+ ] }),
224
+ /* @__PURE__ */ jsxs(Dialog.Footer, { className: "sticky bottom-0 bg-background", children: [
225
+ /* @__PURE__ */ jsx(
226
+ Dialog.CloseTrigger,
227
+ {
228
+ render: /* @__PURE__ */ jsx(Button, { variant: "ghost", color: "default", children: intl.formatMessage(messages.cancel) })
229
+ }
230
+ ),
231
+ /* @__PURE__ */ jsx(
232
+ Button,
233
+ {
234
+ color: "primary",
235
+ onClick: () => {
236
+ onSave({ control: selection, options });
237
+ onOpenChange(false);
238
+ },
239
+ disabled: JSON.stringify(selection) === JSON.stringify(initialSelection) && JSON.stringify(options) === JSON.stringify(initialOptions),
240
+ children: intl.formatMessage(messages.save_settings)
241
+ }
242
+ )
243
+ ] })
244
+ ] })
245
+ ] });
246
+ };
247
+
248
+ export {
249
+ ControlBlockView
250
+ };
@@ -0,0 +1,29 @@
1
+ "use client";
2
+
3
+ // src/components/control-implementation-view.tsx
4
+ import { NodeViewWrapper } from "@tiptap/react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ var ControlImplementationView = (props) => {
7
+ var _a;
8
+ const { node } = props;
9
+ const a = node.attrs;
10
+ return /* @__PURE__ */ jsx(
11
+ NodeViewWrapper,
12
+ {
13
+ as: "div",
14
+ role: "listitem",
15
+ "data-type": "control-implementation",
16
+ "data-id": a.id,
17
+ className: "flex items-start justify-between gap-3 py-3",
18
+ contentEditable: false,
19
+ children: /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
20
+ /* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-foreground truncate", children: (_a = a.title) != null ? _a : a.id }),
21
+ a.description ? /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground mt-0.5", children: a.description }) : null
22
+ ] })
23
+ }
24
+ );
25
+ };
26
+
27
+ export {
28
+ ControlImplementationView
29
+ };
@@ -0,0 +1,10 @@
1
+ "use client";
2
+
3
+ // src/defaults.ts
4
+ var DEFAULT_CONTROL_REF_OPTIONS = {
5
+ showStatus: true
6
+ };
7
+
8
+ export {
9
+ DEFAULT_CONTROL_REF_OPTIONS
10
+ };
@@ -0,0 +1,189 @@
1
+ "use client";
2
+ import {
3
+ ControlPicker
4
+ } from "./chunk-A7FWOQDN.mjs";
5
+ import {
6
+ useControl
7
+ } from "./chunk-4C72VBLP.mjs";
8
+ import {
9
+ messages
10
+ } from "./chunk-D53W4HWR.mjs";
11
+
12
+ // src/components/control-view.tsx
13
+ import { useSafeIntl } from "@kopexa/i18n";
14
+ import {
15
+ Button,
16
+ Callout,
17
+ Chip,
18
+ Dialog,
19
+ Label,
20
+ Switch,
21
+ Tooltip
22
+ } from "@kopexa/sight";
23
+ import { NodeViewWrapper } from "@tiptap/react";
24
+ import { useState } from "react";
25
+ import { useIntl } from "react-intl";
26
+ import { jsx, jsxs } from "react/jsx-runtime";
27
+ var ControlView = (props) => {
28
+ var _a, _b, _c, _d, _e, _f;
29
+ const { node, editor } = props;
30
+ const intl = useIntl();
31
+ const attrs = node.attrs;
32
+ const resolver = props.extension.options.resolver;
33
+ const { isEdit, interactive, ind, mapped, isMissing, isOutdated } = useControl({
34
+ attrs,
35
+ resolver,
36
+ editor
37
+ });
38
+ const [open, setOpen] = useState(false);
39
+ return /* @__PURE__ */ jsxs(NodeViewWrapper, { as: "span", "data-kpx-control": true, "data-id": (_a = attrs.id) != null ? _a : "", children: [
40
+ /* @__PURE__ */ jsxs(
41
+ Chip,
42
+ {
43
+ size: "sm",
44
+ "data-active": open,
45
+ contentEditable: false,
46
+ indicator: ind.indicator,
47
+ indicatorColor: ind.indicatorColor,
48
+ indicatorVariant: ind.indicatorVariant,
49
+ ...((_b = attrs.options) == null ? void 0 : _b.showStatus) && (attrs == null ? void 0 : attrs.status) && { status: attrs.status },
50
+ variant: "bordered",
51
+ color: !attrs.id ? "warning" : isEdit && (isOutdated || isMissing) ? "destructive" : "default",
52
+ onClick: () => {
53
+ setOpen((o) => !o);
54
+ },
55
+ "aria-label": interactive ? "Map control" : "Control",
56
+ tabIndex: interactive ? 0 : -1,
57
+ onKeyDown: (e) => {
58
+ if (!interactive) return;
59
+ if (e.key === "Enter" || e.key === " ") {
60
+ e.preventDefault();
61
+ setOpen((o) => !o);
62
+ }
63
+ },
64
+ children: [
65
+ (_c = attrs.title) != null ? _c : "Unmapped Control",
66
+ isEdit && mapped && isOutdated && !isMissing && /* @__PURE__ */ jsx(Tooltip, { content: intl.formatMessage(messages.outdated_badge), children: /* @__PURE__ */ jsx("span", { className: "ml-1 inline-block h-2 w-2 rounded-full bg-warning" }) }),
67
+ mapped && isMissing && /* @__PURE__ */ jsx(Tooltip, { content: intl.formatMessage(messages.missing_badge), children: /* @__PURE__ */ jsx("span", { className: "ml-1 inline-block h-2 w-2 rounded-full bg-destructive" }) })
68
+ ]
69
+ }
70
+ ),
71
+ interactive && /* @__PURE__ */ jsx(
72
+ EditControlDialog,
73
+ {
74
+ open,
75
+ onOpenChange: setOpen,
76
+ resolver,
77
+ isMissing,
78
+ isOutdated,
79
+ initialSelection: attrs.id ? {
80
+ id: attrs.id,
81
+ title: (_d = attrs.title) != null ? _d : "",
82
+ status: (_e = attrs.status) != null ? _e : null
83
+ } : null,
84
+ initialOptions: (_f = attrs.options) != null ? _f : { showStatus: true },
85
+ onSave: (selection, options) => {
86
+ var _a2, _b2, _c2;
87
+ props.editor.commands.updateControl({
88
+ id: (_a2 = selection == null ? void 0 : selection.id) != null ? _a2 : null,
89
+ title: (_b2 = selection == null ? void 0 : selection.title) != null ? _b2 : null,
90
+ status: (_c2 = selection == null ? void 0 : selection.status) != null ? _c2 : null,
91
+ options: options != null ? options : null,
92
+ updatedAt: selection == null ? void 0 : selection.updatedAt
93
+ });
94
+ }
95
+ }
96
+ )
97
+ ] });
98
+ };
99
+ var EditControlDialog = ({
100
+ open,
101
+ onOpenChange,
102
+ resolver,
103
+ initialSelection,
104
+ initialOptions,
105
+ onSave,
106
+ isMissing,
107
+ isOutdated
108
+ }) => {
109
+ const intl = useSafeIntl();
110
+ const [selection, setSelection] = useState(
111
+ initialSelection
112
+ );
113
+ const [options, setOptions] = useState(initialOptions);
114
+ const isDirty = JSON.stringify(selection) !== JSON.stringify(initialSelection) || JSON.stringify(options) !== JSON.stringify(initialOptions);
115
+ if (!resolver) return null;
116
+ return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, size: "2xl", children: /* @__PURE__ */ jsxs(Dialog.Content, { "aria-label": "Map Control", children: [
117
+ /* @__PURE__ */ jsxs(Dialog.Header, { children: [
118
+ /* @__PURE__ */ jsx(Dialog.Title, { children: (selection == null ? void 0 : selection.title) ? intl.formatMessage(messages.control_with_title, {
119
+ title: selection.title
120
+ }) : intl.formatMessage(messages.map_control) }),
121
+ /* @__PURE__ */ jsx(Dialog.Description, { children: intl.formatMessage(messages.settings_dialog_description) })
122
+ ] }),
123
+ /* @__PURE__ */ jsx(Dialog.Body, { children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-1 gap-6 pt-2", children: [
124
+ (selection == null ? void 0 : selection.id) && isMissing && /* @__PURE__ */ jsx(Callout, { variant: "destructive", children: intl.formatMessage(messages.missing_callout) }),
125
+ !isMissing && isOutdated && /* @__PURE__ */ jsx(Callout, { variant: "warning", children: intl.formatMessage(messages.outdated_callout) }),
126
+ /* @__PURE__ */ jsx(
127
+ ControlPicker,
128
+ {
129
+ resolver,
130
+ value: selection,
131
+ onChange: (next) => setSelection(next),
132
+ debounceMs: 300,
133
+ timeoutMs: 5e3
134
+ }
135
+ ),
136
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
137
+ /* @__PURE__ */ jsx(Label, { children: intl.formatMessage(messages.display_options) }),
138
+ /* @__PURE__ */ jsxs(
139
+ Label,
140
+ {
141
+ variant: "secondary",
142
+ className: "flex items-center justify-between gap-3",
143
+ children: [
144
+ /* @__PURE__ */ jsx("span", { children: intl.formatMessage(messages.show_status_indicator) }),
145
+ /* @__PURE__ */ jsx(
146
+ Switch,
147
+ {
148
+ "aria-label": "Show status indicator",
149
+ checked: !!options.showStatus,
150
+ onCheckedChange: (checked) => setOptions((o) => ({
151
+ ...o,
152
+ showStatus: checked
153
+ }))
154
+ }
155
+ )
156
+ ]
157
+ }
158
+ )
159
+ ] }) })
160
+ ] }) }),
161
+ /* @__PURE__ */ jsxs(Dialog.Footer, { className: "sticky bottom-0 bg-background", children: [
162
+ /* @__PURE__ */ jsx(
163
+ Button,
164
+ {
165
+ variant: "ghost",
166
+ color: "default",
167
+ onClick: () => onOpenChange(false),
168
+ children: intl.formatMessage(messages.cancel)
169
+ }
170
+ ),
171
+ /* @__PURE__ */ jsx(
172
+ Button,
173
+ {
174
+ color: "primary",
175
+ onClick: () => {
176
+ onSave(selection, options);
177
+ onOpenChange(false);
178
+ },
179
+ disabled: !isDirty,
180
+ children: intl.formatMessage(messages.save_settings)
181
+ }
182
+ )
183
+ ] })
184
+ ] }) });
185
+ };
186
+
187
+ export {
188
+ ControlView
189
+ };
@@ -0,0 +1,186 @@
1
+ "use client";
2
+ import {
3
+ createControlBlock
4
+ } from "./chunk-FTEE5U3H.mjs";
5
+ import {
6
+ createControlImplementation
7
+ } from "./chunk-XHD2KFKQ.mjs";
8
+ import {
9
+ getControlNodeTypes
10
+ } from "./chunk-ZUR6XKMG.mjs";
11
+ import {
12
+ DEFAULT_CONTROL_REF_OPTIONS
13
+ } from "./chunk-JM66CQVD.mjs";
14
+ import {
15
+ ControlBlockView
16
+ } from "./chunk-GYDJVHHG.mjs";
17
+
18
+ // src/control-block.ts
19
+ import { mergeAttributes, Node } from "@tiptap/core";
20
+ import { TextSelection } from "@tiptap/pm/state";
21
+ import { ReactNodeViewRenderer } from "@tiptap/react";
22
+ var ControlBlock = Node.create({
23
+ name: "controlBlock",
24
+ controlRole: "controlBlock",
25
+ group: "block",
26
+ isolating: true,
27
+ content: "block+ controlImplementation*",
28
+ addOptions() {
29
+ return {
30
+ resolver: void 0
31
+ };
32
+ },
33
+ addAttributes() {
34
+ return {
35
+ id: { default: null },
36
+ title: { default: null },
37
+ updatedAt: { default: null },
38
+ status: { default: null },
39
+ options: { default: DEFAULT_CONTROL_REF_OPTIONS }
40
+ // JSON Object <- all UI config lives here
41
+ };
42
+ },
43
+ parseHTML() {
44
+ return [{ tag: "div[data-kpx-control-ref]" }];
45
+ },
46
+ renderHTML({ node, HTMLAttributes }) {
47
+ var _a;
48
+ return [
49
+ "span",
50
+ mergeAttributes(HTMLAttributes, {
51
+ "data-kpx-control-ref": "",
52
+ "data-id": node.attrs.id,
53
+ "data-title": node.attrs.title
54
+ }),
55
+ (_a = HTMLAttributes.title) != null ? _a : "Control"
56
+ ];
57
+ },
58
+ addCommands() {
59
+ return {
60
+ insertControlBlock: () => ({ editor, tr, dispatch }) => {
61
+ const node = createControlBlock(editor.schema);
62
+ if (dispatch) {
63
+ const offset = tr.selection.from + 1;
64
+ tr.replaceSelectionWith(node).scrollIntoView().setSelection(TextSelection.near(tr.doc.resolve(offset)));
65
+ }
66
+ return true;
67
+ },
68
+ updateControlBlock: (payload) => ({ tr, state, dispatch }) => {
69
+ var _a, _b, _c, _d, _e;
70
+ const { selection } = state;
71
+ const pos = selection.from;
72
+ const node = tr.doc.nodeAt(pos);
73
+ if (!node || node.type.name !== "controlBlock") return false;
74
+ const next = {
75
+ id: (_a = payload.id) != null ? _a : null,
76
+ title: (_b = payload.title) != null ? _b : null,
77
+ status: (_c = payload.status) != null ? _c : null,
78
+ updatedAt: (_d = payload.updatedAt) != null ? _d : null,
79
+ options: (_e = payload.options) != null ? _e : node.attrs.options
80
+ };
81
+ if (dispatch) {
82
+ tr.setNodeMarkup(pos, void 0, next).scrollIntoView();
83
+ }
84
+ return true;
85
+ },
86
+ setControlImplementationsAt: (blockPos, rows) => ({ state, tr, dispatch }) => {
87
+ const implType = state.schema.nodes.controlImplementation;
88
+ if (!implType) return false;
89
+ const blockNode = state.doc.nodeAt(blockPos);
90
+ if (!blockNode || blockNode.type.name !== this.name) return false;
91
+ const contentStart = blockPos + 1;
92
+ const contentEnd = blockPos + blockNode.nodeSize - 1;
93
+ let firstImplOffset = null;
94
+ let running = 0;
95
+ blockNode.forEach((child) => {
96
+ if (firstImplOffset === null && child.type === implType) {
97
+ firstImplOffset = running;
98
+ }
99
+ running += child.nodeSize;
100
+ });
101
+ const insertPos = firstImplOffset !== null ? contentStart + firstImplOffset : contentEnd;
102
+ if (firstImplOffset !== null) {
103
+ tr.delete(insertPos, contentEnd);
104
+ }
105
+ const types = getControlNodeTypes(state.schema);
106
+ const newNodes = (rows != null ? rows : []).map(
107
+ (r) => createControlImplementation(types.controlImplementation, r)
108
+ ).filter(Boolean);
109
+ if (newNodes.length) {
110
+ tr.insert(insertPos, newNodes);
111
+ }
112
+ if (dispatch) dispatch(tr.scrollIntoView());
113
+ return true;
114
+ },
115
+ setControlImplementations: (rows) => ({ state, tr, dispatch }) => {
116
+ const { $from } = state.selection;
117
+ let blockPos = -1, blockNode = null, depthHit = -1;
118
+ for (let d = $from.depth; d >= 0; d--) {
119
+ const n = $from.node(d);
120
+ if (n.type.name === this.name) {
121
+ blockNode = n;
122
+ depthHit = d;
123
+ blockPos = $from.start(d);
124
+ break;
125
+ }
126
+ }
127
+ if (!blockNode || blockPos < 0) return false;
128
+ const implType = state.schema.nodes.controlImplementation;
129
+ if (!implType) return false;
130
+ let offset = 0;
131
+ let firstImplOffset = null;
132
+ for (let i = 0; i < blockNode.childCount; i++) {
133
+ const child = blockNode.child(i);
134
+ if (child.type === implType && firstImplOffset === null) {
135
+ firstImplOffset = offset;
136
+ }
137
+ offset += child.nodeSize;
138
+ }
139
+ const blockContentStart = blockPos + 1;
140
+ const blockContentEnd = blockPos + blockNode.nodeSize - 1;
141
+ const insertPos = firstImplOffset !== null ? blockContentStart + firstImplOffset : blockContentEnd;
142
+ if (firstImplOffset !== null) {
143
+ tr.delete(blockContentStart + firstImplOffset, blockContentEnd);
144
+ }
145
+ const types = getControlNodeTypes(state.schema);
146
+ const newNodes = rows.map(
147
+ (r) => createControlImplementation(types.controlImplementation, r)
148
+ ).filter(Boolean);
149
+ if (newNodes.length) {
150
+ tr.insert(insertPos, newNodes);
151
+ }
152
+ if (dispatch) dispatch(tr.scrollIntoView());
153
+ return true;
154
+ },
155
+ appendControlImplementations: (rows) => ({ state, tr, dispatch }) => {
156
+ const { $from } = state.selection;
157
+ let blockPos = -1, blockNode = null;
158
+ for (let d = $from.depth; d >= 0; d--) {
159
+ const n = $from.node(d);
160
+ if (n.type.name === this.name) {
161
+ blockNode = n;
162
+ blockPos = $from.start(d);
163
+ break;
164
+ }
165
+ }
166
+ if (!blockNode || blockPos < 0) return false;
167
+ const blockContentEnd = blockPos + blockNode.nodeSize - 1;
168
+ const types = getControlNodeTypes(state.schema);
169
+ const newNodes = rows.map(
170
+ (r) => createControlImplementation(types.controlImplementation, r)
171
+ ).filter(Boolean);
172
+ if (!newNodes.length) return true;
173
+ tr.insert(blockContentEnd, newNodes);
174
+ if (dispatch) dispatch(tr.scrollIntoView());
175
+ return true;
176
+ }
177
+ };
178
+ },
179
+ addNodeView() {
180
+ return ReactNodeViewRenderer(ControlBlockView, { as: "div" });
181
+ }
182
+ });
183
+
184
+ export {
185
+ ControlBlock
186
+ };