@aglyn/besigner 1.0.0-beta.143

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 (99) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +7 -0
  3. package/package.json +48 -0
  4. package/src/besigner.d.ts +28 -0
  5. package/src/besigner.js +59 -0
  6. package/src/besigner.js.map +1 -0
  7. package/src/index.d.ts +17 -0
  8. package/src/index.js +18 -0
  9. package/src/index.js.map +1 -0
  10. package/src/lib/api/app.api.d.ts +22 -0
  11. package/src/lib/api/app.api.js +59 -0
  12. package/src/lib/api/app.api.js.map +1 -0
  13. package/src/lib/api/besigner.api.d.ts +24 -0
  14. package/src/lib/api/besigner.api.js +39 -0
  15. package/src/lib/api/besigner.api.js.map +1 -0
  16. package/src/lib/clipboard-manager/clipboard-manager.d.ts +89 -0
  17. package/src/lib/clipboard-manager/clipboard-manager.js +241 -0
  18. package/src/lib/clipboard-manager/clipboard-manager.js.map +1 -0
  19. package/src/lib/clipboard-manager/clipboard-mirror.d.ts +52 -0
  20. package/src/lib/clipboard-manager/clipboard-mirror.js +75 -0
  21. package/src/lib/clipboard-manager/clipboard-mirror.js.map +1 -0
  22. package/src/lib/clipboard-manager/index.d.ts +20 -0
  23. package/src/lib/clipboard-manager/index.js +23 -0
  24. package/src/lib/clipboard-manager/index.js.map +1 -0
  25. package/src/lib/clipboard-manager/style-clipboard.d.ts +77 -0
  26. package/src/lib/clipboard-manager/style-clipboard.js +173 -0
  27. package/src/lib/clipboard-manager/style-clipboard.js.map +1 -0
  28. package/src/lib/constants/_internal.d.ts +20 -0
  29. package/src/lib/constants/_internal.js +19 -0
  30. package/src/lib/constants/_internal.js.map +1 -0
  31. package/src/lib/constants/besigner.d.ts +78 -0
  32. package/src/lib/constants/besigner.js +69 -0
  33. package/src/lib/constants/besigner.js.map +1 -0
  34. package/src/lib/controllers/besigner-app.controller.d.ts +33 -0
  35. package/src/lib/controllers/besigner-app.controller.js +57 -0
  36. package/src/lib/controllers/besigner-app.controller.js.map +1 -0
  37. package/src/lib/controllers/besigner-interface.controller.d.ts +44 -0
  38. package/src/lib/controllers/besigner-interface.controller.js +130 -0
  39. package/src/lib/controllers/besigner-interface.controller.js.map +1 -0
  40. package/src/lib/definitions/besigner-app.types.d.ts +41 -0
  41. package/src/lib/definitions/besigner-app.types.js +18 -0
  42. package/src/lib/definitions/besigner-app.types.js.map +1 -0
  43. package/src/lib/definitions/besigner-interface.types.d.ts +106 -0
  44. package/src/lib/definitions/besigner-interface.types.js +18 -0
  45. package/src/lib/definitions/besigner-interface.types.js.map +1 -0
  46. package/src/lib/definitions/emitter.types.d.ts +33 -0
  47. package/src/lib/definitions/emitter.types.js +18 -0
  48. package/src/lib/definitions/emitter.types.js.map +1 -0
  49. package/src/lib/device-preview-width.d.ts +39 -0
  50. package/src/lib/device-preview-width.js +57 -0
  51. package/src/lib/device-preview-width.js.map +1 -0
  52. package/src/lib/dnd-manager/confirm-valid-lineal-relationship.d.ts +54 -0
  53. package/src/lib/dnd-manager/confirm-valid-lineal-relationship.js +109 -0
  54. package/src/lib/dnd-manager/confirm-valid-lineal-relationship.js.map +1 -0
  55. package/src/lib/dnd-manager/dnd-manager.d.ts +75 -0
  56. package/src/lib/dnd-manager/dnd-manager.js +337 -0
  57. package/src/lib/dnd-manager/dnd-manager.js.map +1 -0
  58. package/src/lib/dnd-manager/droppable-region-utils.d.ts +72 -0
  59. package/src/lib/dnd-manager/droppable-region-utils.js +115 -0
  60. package/src/lib/dnd-manager/droppable-region-utils.js.map +1 -0
  61. package/src/lib/dnd-manager/index.d.ts +20 -0
  62. package/src/lib/dnd-manager/index.js +21 -0
  63. package/src/lib/dnd-manager/index.js.map +1 -0
  64. package/src/lib/focus-manager/focus-manager.d.ts +104 -0
  65. package/src/lib/focus-manager/focus-manager.js +353 -0
  66. package/src/lib/focus-manager/focus-manager.js.map +1 -0
  67. package/src/lib/focus-manager/index.d.ts +18 -0
  68. package/src/lib/focus-manager/index.js +19 -0
  69. package/src/lib/focus-manager/index.js.map +1 -0
  70. package/src/lib/is-root-element-id.d.ts +19 -0
  71. package/src/lib/is-root-element-id.js +22 -0
  72. package/src/lib/is-root-element-id.js.map +1 -0
  73. package/src/lib/managers.d.ts +25 -0
  74. package/src/lib/managers.js +26 -0
  75. package/src/lib/managers.js.map +1 -0
  76. package/src/lib/node-move/index.d.ts +17 -0
  77. package/src/lib/node-move/index.js +18 -0
  78. package/src/lib/node-move/index.js.map +1 -0
  79. package/src/lib/node-move/node-move.d.ts +80 -0
  80. package/src/lib/node-move/node-move.js +134 -0
  81. package/src/lib/node-move/node-move.js.map +1 -0
  82. package/src/lib/node-refs/index.d.ts +1 -0
  83. package/src/lib/node-refs/index.js +3 -0
  84. package/src/lib/node-refs/index.js.map +1 -0
  85. package/src/lib/node-refs/node-refs.d.ts +24 -0
  86. package/src/lib/node-refs/node-refs.js +30 -0
  87. package/src/lib/node-refs/node-refs.js.map +1 -0
  88. package/src/lib/pick-manager/index.d.ts +18 -0
  89. package/src/lib/pick-manager/index.js +20 -0
  90. package/src/lib/pick-manager/index.js.map +1 -0
  91. package/src/lib/pick-manager/pick-manager.d.ts +64 -0
  92. package/src/lib/pick-manager/pick-manager.js +116 -0
  93. package/src/lib/pick-manager/pick-manager.js.map +1 -0
  94. package/src/lib/text-entry/index.d.ts +17 -0
  95. package/src/lib/text-entry/index.js +18 -0
  96. package/src/lib/text-entry/index.js.map +1 -0
  97. package/src/lib/text-entry/text-entry.d.ts +71 -0
  98. package/src/lib/text-entry/text-entry.js +103 -0
  99. package/src/lib/text-entry/text-entry.js.map +1 -0
@@ -0,0 +1,80 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type * as Aglyn from '@aglyn/aglyn';
18
+ /**
19
+ * Moving an existing node between containers by CLICKING (AGL-1405).
20
+ *
21
+ * Until this existed, every reparent in the editor went through one gesture —
22
+ * drag-and-drop — and a node that ended up in the wrong container could only
23
+ * be rescued through the Raw JSON editor. That is not a repair path a
24
+ * click-built workflow can use at all, and AGL-1388 made it matter: the
25
+ * moment a component starts REFUSING children, everything already inside one
26
+ * is stranded with no way out.
27
+ *
28
+ * Two actions are enough to reach anywhere in the tree, because the hierarchy
29
+ * already has Shift up / Shift down:
30
+ *
31
+ * - `moveNodeOut` lifts a node out of its container, landing it just after
32
+ * that container among its aunts and uncles.
33
+ * - `moveNodeIn` tucks a node into the sibling directly above it.
34
+ *
35
+ * Out, shift, in. Both refuse — rather than strand — anything the renderer
36
+ * could not draw, which is the entire reason the /press screenshots are
37
+ * stuck: `nodeAcceptsChildren` and the lineal rules are checked BEFORE
38
+ * anything is written, exactly as `pasteInto` checks them.
39
+ */
40
+ /**
41
+ * A plain result object rather than a discriminated union, matching
42
+ * `PasteResult`: an `ok: true | false` union stops narrowing once it crosses
43
+ * a library boundary. Callers test `error`.
44
+ */
45
+ export interface MoveResult {
46
+ /** The moved node — absent when `error` is set and nothing was written. */
47
+ node?: Aglyn.NodeSchema<any>;
48
+ /** Set when the move was refused, explaining why. */
49
+ error?: string;
50
+ }
51
+ /** Where a move would land, or why it is not offered. */
52
+ interface MoveTarget {
53
+ parent?: Aglyn.NodeSchema<any>;
54
+ index?: number;
55
+ error?: string;
56
+ }
57
+ /**
58
+ * Resolve "Move out of container": the node becomes the next sibling of the
59
+ * container it is currently in.
60
+ *
61
+ * Landing it right AFTER its old parent rather than appending to the
62
+ * grandparent keeps the node where the author is looking — the /press images
63
+ * belong beside their markdown block, not at the bottom of the section.
64
+ */
65
+ export declare function resolveMoveOut(node: Aglyn.NodeSchema<any>): MoveTarget;
66
+ /**
67
+ * Resolve "Move into previous": the node is appended to the sibling directly
68
+ * above it. The inverse of `resolveMoveOut`, and the half that lets a click
69
+ * put something INTO a container rather than only lift it out.
70
+ */
71
+ export declare function resolveMoveIn(node: Aglyn.NodeSchema<any>): MoveTarget;
72
+ /** Lift `node` out of its container, landing it just after that container. */
73
+ export declare function moveNodeOut(node: Aglyn.NodeSchema<any>): MoveResult;
74
+ /** Tuck `node` into the sibling directly above it. */
75
+ export declare function moveNodeIn(node: Aglyn.NodeSchema<any>): MoveResult;
76
+ /** Whether the action is offered at all — for a menu item's `disabled`. */
77
+ export declare function canMoveNodeOut(node: Aglyn.NodeSchema<any>): boolean;
78
+ /** Whether the action is offered at all — for a menu item's `disabled`. */
79
+ export declare function canMoveNodeIn(node: Aglyn.NodeSchema<any>): boolean;
80
+ export {};
@@ -0,0 +1,134 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { canvas } from "@aglyn/aglyn";
17
+ import { confirmValidLinealRelationship, describeInvalidLinealRelationship } from "../dnd-manager/confirm-valid-lineal-relationship.js";
18
+ function linealActor(node) {
19
+ var _node_componentSchema, _node_componentSchema1;
20
+ return {
21
+ pluginId: node == null ? void 0 : node.pluginId,
22
+ componentId: node == null ? void 0 : node.componentId,
23
+ restrictChildren: node == null ? void 0 : (_node_componentSchema = node.componentSchema) == null ? void 0 : _node_componentSchema.restrictChildren,
24
+ restrictParent: node == null ? void 0 : (_node_componentSchema1 = node.componentSchema) == null ? void 0 : _node_componentSchema1.restrictParent
25
+ };
26
+ }
27
+ /**
28
+ * The shared refusal set. `nodeAcceptsChildren` is the AGL-1388 gate — a
29
+ * `markdown` block, a Reusable Component instance, a Layout Slot, a List Item
30
+ * Text or any leaf renders its own content and nothing else, so a node moved
31
+ * inside one is saved forever and drawn never. The lineal rules are the
32
+ * placement rules drag-and-drop and paste already enforce; skipping them here
33
+ * would let a click build an arrangement a drag then (correctly) refuses.
34
+ */ function confirmTarget(node, parent, index) {
35
+ if (!canvas.nodeAcceptsChildren(parent)) {
36
+ return {
37
+ error: `${parent.labelShort} can't hold other elements`
38
+ };
39
+ }
40
+ const item = linealActor(node);
41
+ const into = linealActor(parent);
42
+ const [valid, reason] = confirmValidLinealRelationship(item, into);
43
+ if (!valid) {
44
+ return {
45
+ error: describeInvalidLinealRelationship(item, into, reason)
46
+ };
47
+ }
48
+ return {
49
+ parent,
50
+ index
51
+ };
52
+ }
53
+ /**
54
+ * Resolve "Move out of container": the node becomes the next sibling of the
55
+ * container it is currently in.
56
+ *
57
+ * Landing it right AFTER its old parent rather than appending to the
58
+ * grandparent keeps the node where the author is looking — the /press images
59
+ * belong beside their markdown block, not at the bottom of the section.
60
+ */ export function resolveMoveOut(node) {
61
+ if (!node || canvas.isRootNode(node)) {
62
+ return {
63
+ error: 'There is nothing to move'
64
+ };
65
+ }
66
+ const parent = node.parent;
67
+ if (!parent) return {
68
+ error: 'This element has no container'
69
+ };
70
+ if (canvas.isRootNode(parent)) {
71
+ return {
72
+ error: 'This element is already at the top level'
73
+ };
74
+ }
75
+ const grandparent = parent.parent;
76
+ if (!grandparent) return {
77
+ error: 'This element is already at the top level'
78
+ };
79
+ const at = canvas.getNodeIndex(parent);
80
+ return confirmTarget(node, grandparent, at > -1 ? at + 1 : NaN);
81
+ }
82
+ /**
83
+ * Resolve "Move into previous": the node is appended to the sibling directly
84
+ * above it. The inverse of `resolveMoveOut`, and the half that lets a click
85
+ * put something INTO a container rather than only lift it out.
86
+ */ export function resolveMoveIn(node) {
87
+ var _parent_nodes;
88
+ if (!node || canvas.isRootNode(node)) {
89
+ return {
90
+ error: 'There is nothing to move'
91
+ };
92
+ }
93
+ const parent = node.parent;
94
+ if (!parent) return {
95
+ error: 'This element has no container'
96
+ };
97
+ const at = canvas.getNodeIndex(node);
98
+ if (at < 1) return {
99
+ error: 'There is no element above this one'
100
+ };
101
+ const previous = canvas.getNode((_parent_nodes = parent.nodes) == null ? void 0 : _parent_nodes[at - 1]);
102
+ if (!previous) return {
103
+ error: 'There is no element above this one'
104
+ };
105
+ // NaN appends, so the node lands at the end of its new container — where
106
+ // it reads as "the last thing added", matching the Insert menu.
107
+ return confirmTarget(node, previous, NaN);
108
+ }
109
+ function apply(target, node) {
110
+ if (target.error) return {
111
+ error: target.error
112
+ };
113
+ // `reparentNode`, not delete-and-recreate: the node keeps its id, its
114
+ // subtree and its place in history (`deleteNode` recurses over the whole
115
+ // subtree, so rebuilding would re-mint every id beneath it and break any
116
+ // interaction that referenced one).
117
+ return {
118
+ node: canvas.reparentNode(node, target.parent, target.index)
119
+ };
120
+ }
121
+ /** Lift `node` out of its container, landing it just after that container. */ export function moveNodeOut(node) {
122
+ return apply(resolveMoveOut(node), node);
123
+ }
124
+ /** Tuck `node` into the sibling directly above it. */ export function moveNodeIn(node) {
125
+ return apply(resolveMoveIn(node), node);
126
+ }
127
+ /** Whether the action is offered at all — for a menu item's `disabled`. */ export function canMoveNodeOut(node) {
128
+ return !resolveMoveOut(node).error;
129
+ }
130
+ /** Whether the action is offered at all — for a menu item's `disabled`. */ export function canMoveNodeIn(node) {
131
+ return !resolveMoveIn(node).error;
132
+ }
133
+
134
+ //# sourceMappingURL=node-move.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/node-move/node-move.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type * as Aglyn from '@aglyn/aglyn'\nimport { canvas } from '@aglyn/aglyn'\nimport {\n confirmValidLinealRelationship,\n describeInvalidLinealRelationship,\n type LinealItem,\n} from '../dnd-manager/confirm-valid-lineal-relationship'\n\n/**\n * Moving an existing node between containers by CLICKING (AGL-1405).\n *\n * Until this existed, every reparent in the editor went through one gesture —\n * drag-and-drop — and a node that ended up in the wrong container could only\n * be rescued through the Raw JSON editor. That is not a repair path a\n * click-built workflow can use at all, and AGL-1388 made it matter: the\n * moment a component starts REFUSING children, everything already inside one\n * is stranded with no way out.\n *\n * Two actions are enough to reach anywhere in the tree, because the hierarchy\n * already has Shift up / Shift down:\n *\n * - `moveNodeOut` lifts a node out of its container, landing it just after\n * that container among its aunts and uncles.\n * - `moveNodeIn` tucks a node into the sibling directly above it.\n *\n * Out, shift, in. Both refuse — rather than strand — anything the renderer\n * could not draw, which is the entire reason the /press screenshots are\n * stuck: `nodeAcceptsChildren` and the lineal rules are checked BEFORE\n * anything is written, exactly as `pasteInto` checks them.\n */\n\n/**\n * A plain result object rather than a discriminated union, matching\n * `PasteResult`: an `ok: true | false` union stops narrowing once it crosses\n * a library boundary. Callers test `error`.\n */\nexport interface MoveResult {\n /** The moved node — absent when `error` is set and nothing was written. */\n node?: Aglyn.NodeSchema<any>\n /** Set when the move was refused, explaining why. */\n error?: string\n}\n\n/** Where a move would land, or why it is not offered. */\ninterface MoveTarget {\n parent?: Aglyn.NodeSchema<any>\n index?: number\n error?: string\n}\n\nfunction linealActor(node: Aglyn.NodeSchema<any>): LinealItem {\n return {\n pluginId: node?.pluginId,\n componentId: node?.componentId,\n restrictChildren: node?.componentSchema?.restrictChildren,\n restrictParent: node?.componentSchema?.restrictParent,\n }\n}\n\n/**\n * The shared refusal set. `nodeAcceptsChildren` is the AGL-1388 gate — a\n * `markdown` block, a Reusable Component instance, a Layout Slot, a List Item\n * Text or any leaf renders its own content and nothing else, so a node moved\n * inside one is saved forever and drawn never. The lineal rules are the\n * placement rules drag-and-drop and paste already enforce; skipping them here\n * would let a click build an arrangement a drag then (correctly) refuses.\n */\nfunction confirmTarget(\n node: Aglyn.NodeSchema<any>,\n parent: Aglyn.NodeSchema<any>,\n index: number,\n): MoveTarget {\n if (!canvas.nodeAcceptsChildren(parent)) {\n return { error: `${parent.labelShort} can't hold other elements` }\n }\n const item = linealActor(node)\n const into = linealActor(parent)\n const [valid, reason] = confirmValidLinealRelationship(item, into)\n if (!valid) {\n return { error: describeInvalidLinealRelationship(item, into, reason) }\n }\n return { parent, index }\n}\n\n/**\n * Resolve \"Move out of container\": the node becomes the next sibling of the\n * container it is currently in.\n *\n * Landing it right AFTER its old parent rather than appending to the\n * grandparent keeps the node where the author is looking — the /press images\n * belong beside their markdown block, not at the bottom of the section.\n */\nexport function resolveMoveOut(node: Aglyn.NodeSchema<any>): MoveTarget {\n if (!node || canvas.isRootNode(node)) {\n return { error: 'There is nothing to move' }\n }\n const parent = node.parent\n if (!parent) return { error: 'This element has no container' }\n if (canvas.isRootNode(parent)) {\n return { error: 'This element is already at the top level' }\n }\n const grandparent = parent.parent\n if (!grandparent) return { error: 'This element is already at the top level' }\n\n const at = canvas.getNodeIndex(parent)\n return confirmTarget(node, grandparent, at > -1 ? at + 1 : NaN)\n}\n\n/**\n * Resolve \"Move into previous\": the node is appended to the sibling directly\n * above it. The inverse of `resolveMoveOut`, and the half that lets a click\n * put something INTO a container rather than only lift it out.\n */\nexport function resolveMoveIn(node: Aglyn.NodeSchema<any>): MoveTarget {\n if (!node || canvas.isRootNode(node)) {\n return { error: 'There is nothing to move' }\n }\n const parent = node.parent\n if (!parent) return { error: 'This element has no container' }\n\n const at = canvas.getNodeIndex(node)\n if (at < 1) return { error: 'There is no element above this one' }\n const previous = canvas.getNode(parent.nodes?.[at - 1])\n if (!previous) return { error: 'There is no element above this one' }\n\n // NaN appends, so the node lands at the end of its new container — where\n // it reads as \"the last thing added\", matching the Insert menu.\n return confirmTarget(node, previous, NaN)\n}\n\nfunction apply(target: MoveTarget, node: Aglyn.NodeSchema<any>): MoveResult {\n if (target.error) return { error: target.error }\n // `reparentNode`, not delete-and-recreate: the node keeps its id, its\n // subtree and its place in history (`deleteNode` recurses over the whole\n // subtree, so rebuilding would re-mint every id beneath it and break any\n // interaction that referenced one).\n return { node: canvas.reparentNode(node, target.parent!, target.index) }\n}\n\n/** Lift `node` out of its container, landing it just after that container. */\nexport function moveNodeOut(node: Aglyn.NodeSchema<any>): MoveResult {\n return apply(resolveMoveOut(node), node)\n}\n\n/** Tuck `node` into the sibling directly above it. */\nexport function moveNodeIn(node: Aglyn.NodeSchema<any>): MoveResult {\n return apply(resolveMoveIn(node), node)\n}\n\n/** Whether the action is offered at all — for a menu item's `disabled`. */\nexport function canMoveNodeOut(node: Aglyn.NodeSchema<any>): boolean {\n return !resolveMoveOut(node).error\n}\n\n/** Whether the action is offered at all — for a menu item's `disabled`. */\nexport function canMoveNodeIn(node: Aglyn.NodeSchema<any>): boolean {\n return !resolveMoveIn(node).error\n}\n"],"names":["canvas","confirmValidLinealRelationship","describeInvalidLinealRelationship","linealActor","node","pluginId","componentId","restrictChildren","componentSchema","restrictParent","confirmTarget","parent","index","nodeAcceptsChildren","error","labelShort","item","into","valid","reason","resolveMoveOut","isRootNode","grandparent","at","getNodeIndex","NaN","resolveMoveIn","previous","getNode","nodes","apply","target","reparentNode","moveNodeOut","moveNodeIn","canMoveNodeOut","canMoveNodeIn"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export * from './node-refs';
@@ -0,0 +1,3 @@
1
+ export * from "./node-refs.js";
2
+
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/node-refs/index.ts"],"sourcesContent":["export * from './node-refs'\n"],"names":[],"mappings":"AAAA,cAAc,iBAAa"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import type { RefObject } from 'react';
18
+ export declare enum EditorMode {
19
+ SELECT = 1,
20
+ REARRANGE = 2,
21
+ PREVIEW = 3
22
+ }
23
+ export declare const refs: import("mobx").ObservableMap<string, RefObject<HTMLElement>>;
24
+ export declare const handles: import("mobx").ObservableMap<string, Partial<Record<JSX.Key.Any, unknown>>>;
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2023 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { observable } from "mobx";
17
+ export var EditorMode = /*#__PURE__*/ function(EditorMode) {
18
+ EditorMode[EditorMode["SELECT"] = 0x1] = "SELECT";
19
+ EditorMode[EditorMode["REARRANGE"] = 0x2] = "REARRANGE";
20
+ EditorMode[EditorMode["PREVIEW"] = 0x3] = "PREVIEW";
21
+ return EditorMode;
22
+ }({});
23
+ export const refs = observable.map({}, {
24
+ deep: false
25
+ });
26
+ export const handles = observable.map({}, {
27
+ deep: false
28
+ });
29
+
30
+ //# sourceMappingURL=node-refs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/node-refs/node-refs.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2023 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type * as Aglyn from '@aglyn/aglyn'\nimport { observable } from 'mobx'\nimport type { RefObject } from 'react'\n\nexport enum EditorMode { //BesignerDeviceFlag\n SELECT = 0x1,\n REARRANGE = 0x2,\n PREVIEW = 0x3,\n}\n\nexport const refs = observable.map<Aglyn.NodeId, RefObject<HTMLElement>>(\n {},\n { deep: false },\n)\nexport const handles = observable.map<Aglyn.NodeId, JSX.AnyProps>(\n {},\n { deep: false },\n)\n"],"names":["observable","EditorMode","refs","map","deep","handles"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAGD,SAASA,UAAU,QAAQ,OAAM;AAGjC,OAAO,IAAA,AAAKC,oCAAAA;sCACD;yCACG;uCACF;WAHAA;MAIX;AAED,OAAO,MAAMC,OAAOF,WAAWG,GAAG,CAChC,CAAC,GACD;IAAEC,MAAM;AAAM,GACf;AACD,OAAO,MAAMC,UAAUL,WAAWG,GAAG,CACnC,CAAC,GACD;IAAEC,MAAM;AAAM,GACf"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ export * as pick from './pick-manager';
18
+ export { type PickHandler, type StartPickOptions, nodeElementLabel, } from './pick-manager';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import * as _pick from "./pick-manager.js";
17
+ export { _pick as pick };
18
+ export { nodeElementLabel } from "./pick-manager.js";
19
+
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/pick-manager/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport * as pick from './pick-manager'\nexport {\n type PickHandler,\n type StartPickOptions,\n nodeElementLabel,\n} from './pick-manager'\n"],"names":["pick","nodeElementLabel"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,uBAAsB,oBAAgB;AAAtC,SAAO,SAAKA,IAAI,GAAsB;AACtC,SAGEC,gBAAgB,QACX,oBAAgB"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ /**
18
+ * Canvas element-picker (AGL-574): the bridge that lets the console's
19
+ * interaction builder point at an element by *clicking it on the canvas*
20
+ * instead of hand-writing a CSS selector. The dialog calls {@link startPick}
21
+ * with a callback and minimizes itself; the canvas leaves read
22
+ * {@link isPicking} to paint a pick affordance and route the next click
23
+ * through {@link handlePickClick}, which resolves the leaf's node id + a
24
+ * human label and hands both back to the dialog before exiting pick mode.
25
+ *
26
+ * A MobX store (mirroring the focus-manager seam) so the canvas
27
+ * `node-leaf` / `draggable-droppable` observers react without threading
28
+ * React context through the dnd layer, while the console dialog drives it
29
+ * imperatively via the exported functions. The picked selector is the RAW
30
+ * canvas id — `[data-aglyn="leaf:<id>"]` — which resolves on the live site
31
+ * thanks to AGL-573's prefix-insensitive matching.
32
+ */
33
+ export type PickHandler = (nodeId: string, label: string) => void;
34
+ export interface StartPickOptions {
35
+ /** Prompt shown in the picking banner (e.g. "Click a menu element"). */
36
+ hint?: string;
37
+ /** Invoked when the user aborts the pick (Escape / Cancel). */
38
+ onCancel?: () => void;
39
+ }
40
+ /** Reactive: true while a pick is in progress (read from canvas observers). */
41
+ export declare function isPicking(): boolean;
42
+ /** Reactive: the current picking banner prompt, if any. */
43
+ export declare function getHint(): string | undefined;
44
+ /**
45
+ * Enters pick mode. The next canvas leaf click resolves to
46
+ * `handler(nodeId, label)`; Escape (or {@link cancelPick}) aborts and runs
47
+ * `options.onCancel`. Starting a new pick supersedes any in-flight one.
48
+ */
49
+ export declare function startPick(handler: PickHandler, options?: StartPickOptions): void;
50
+ /** Aborts the current pick and notifies the caller's `onCancel`. */
51
+ export declare function cancelPick(): void;
52
+ /**
53
+ * Canvas-side entry point: the leaf that was clicked while picking hands us
54
+ * its node id. Resolves a human label, exits pick mode, then fires the
55
+ * dialog's callback. No-ops when not picking so a stray click is harmless.
56
+ */
57
+ export declare function handlePickClick(nodeId: string): void;
58
+ /**
59
+ * A friendly, human-readable label for a canvas node — its component's
60
+ * display name, the first string child in quotes when present, and the raw
61
+ * componentId in parentheses (e.g. `Dropdown "Shop" (muiNavMenu)`). Shared
62
+ * by the picker callback and the dialog's target chip so both read the same.
63
+ */
64
+ export declare function nodeElementLabel(nodeId: string): string;
@@ -0,0 +1,116 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ import { canvas, components } from "@aglyn/aglyn";
17
+ import { observable, runInAction } from "mobx";
18
+ import { isTextEntryElement, isTextEntryFocused } from "../text-entry/index.js";
19
+ const state = observable({
20
+ isPicking: false,
21
+ hint: undefined
22
+ });
23
+ // Handler refs live outside the observable — they are plain callbacks, not
24
+ // reactive state, and must not be wrapped by MobX.
25
+ let onPicked = null;
26
+ let onCancel = null;
27
+ let escapeListener = null;
28
+ /** Reactive: true while a pick is in progress (read from canvas observers). */ export function isPicking() {
29
+ return state.isPicking;
30
+ }
31
+ /** Reactive: the current picking banner prompt, if any. */ export function getHint() {
32
+ return state.hint;
33
+ }
34
+ /**
35
+ * Enters pick mode. The next canvas leaf click resolves to
36
+ * `handler(nodeId, label)`; Escape (or {@link cancelPick}) aborts and runs
37
+ * `options.onCancel`. Starting a new pick supersedes any in-flight one.
38
+ */ export function startPick(handler, options = {}) {
39
+ var _options_onCancel;
40
+ teardownEscape();
41
+ onPicked = handler;
42
+ onCancel = (_options_onCancel = options.onCancel) != null ? _options_onCancel : null;
43
+ runInAction(()=>{
44
+ state.isPicking = true;
45
+ state.hint = options.hint;
46
+ });
47
+ if (typeof window !== 'undefined') {
48
+ escapeListener = (event)=>{
49
+ if (event.key !== 'Escape') return;
50
+ // Pick mode only MINIMIZES the interaction builder — the whole
51
+ // besigner (attributes panel, custom-CSS field, raw JSON editor,
52
+ // inline editors) stays live underneath. A capture-phase Escape that
53
+ // ignores focus therefore steals the keystroke a field owns: closing
54
+ // a Select/Autocomplete popper, reverting an inline text edit, or
55
+ // dismissing Monaco's find widget. Text entry wins; the banner's
56
+ // Cancel button, and Escape once focus leaves the field, still abort
57
+ // the pick (AGL-2212).
58
+ if (isTextEntryElement(event.target) || isTextEntryFocused()) return;
59
+ event.preventDefault();
60
+ event.stopPropagation();
61
+ cancelPick();
62
+ };
63
+ // Capture phase so the canvas/dialog can't swallow the abort first.
64
+ window.addEventListener('keydown', escapeListener, true);
65
+ }
66
+ }
67
+ /** Aborts the current pick and notifies the caller's `onCancel`. */ export function cancelPick() {
68
+ if (!state.isPicking && !onPicked) return;
69
+ const cancel = onCancel;
70
+ teardown();
71
+ cancel == null ? void 0 : cancel();
72
+ }
73
+ /**
74
+ * Canvas-side entry point: the leaf that was clicked while picking hands us
75
+ * its node id. Resolves a human label, exits pick mode, then fires the
76
+ * dialog's callback. No-ops when not picking so a stray click is harmless.
77
+ */ export function handlePickClick(nodeId) {
78
+ if (!state.isPicking) return;
79
+ const handler = onPicked;
80
+ const label = nodeElementLabel(nodeId);
81
+ teardown();
82
+ handler == null ? void 0 : handler(nodeId, label);
83
+ }
84
+ function teardown() {
85
+ onPicked = null;
86
+ onCancel = null;
87
+ teardownEscape();
88
+ runInAction(()=>{
89
+ state.isPicking = false;
90
+ state.hint = undefined;
91
+ });
92
+ }
93
+ function teardownEscape() {
94
+ if (escapeListener && typeof window !== 'undefined') {
95
+ window.removeEventListener('keydown', escapeListener, true);
96
+ }
97
+ escapeListener = null;
98
+ }
99
+ /**
100
+ * A friendly, human-readable label for a canvas node — its component's
101
+ * display name, the first string child in quotes when present, and the raw
102
+ * componentId in parentheses (e.g. `Dropdown "Shop" (muiNavMenu)`). Shared
103
+ * by the picker callback and the dialog's target chip so both read the same.
104
+ */ export function nodeElementLabel(nodeId) {
105
+ var _ref;
106
+ var _components_getSchema, _node_props;
107
+ const node = canvas.getNode(nodeId);
108
+ const componentId = String((_ref = node == null ? void 0 : node.componentId) != null ? _ref : '');
109
+ const displayName = ((_components_getSchema = components.getSchema(componentId)) == null ? void 0 : _components_getSchema.displayName) || componentId || 'Element';
110
+ const rawChildren = node == null ? void 0 : (_node_props = node.props) == null ? void 0 : _node_props.children;
111
+ const text = typeof rawChildren === 'string' ? rawChildren.trim().slice(0, 24) : '';
112
+ const suffix = componentId && componentId !== displayName ? ` (${componentId})` : '';
113
+ return `${displayName}${text ? ` "${text}"` : ''}${suffix}`;
114
+ }
115
+
116
+ //# sourceMappingURL=pick-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/pick-manager/pick-manager.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type * as Aglyn from '@aglyn/aglyn'\nimport { canvas, components } from '@aglyn/aglyn'\nimport { observable, runInAction } from 'mobx'\nimport { isTextEntryElement, isTextEntryFocused } from '../text-entry'\n\n/**\n * Canvas element-picker (AGL-574): the bridge that lets the console's\n * interaction builder point at an element by *clicking it on the canvas*\n * instead of hand-writing a CSS selector. The dialog calls {@link startPick}\n * with a callback and minimizes itself; the canvas leaves read\n * {@link isPicking} to paint a pick affordance and route the next click\n * through {@link handlePickClick}, which resolves the leaf's node id + a\n * human label and hands both back to the dialog before exiting pick mode.\n *\n * A MobX store (mirroring the focus-manager seam) so the canvas\n * `node-leaf` / `draggable-droppable` observers react without threading\n * React context through the dnd layer, while the console dialog drives it\n * imperatively via the exported functions. The picked selector is the RAW\n * canvas id — `[data-aglyn=\"leaf:<id>\"]` — which resolves on the live site\n * thanks to AGL-573's prefix-insensitive matching.\n */\nexport type PickHandler = (nodeId: string, label: string) => void\n\nexport interface StartPickOptions {\n /** Prompt shown in the picking banner (e.g. \"Click a menu element\"). */\n hint?: string\n /** Invoked when the user aborts the pick (Escape / Cancel). */\n onCancel?: () => void\n}\n\ninterface PickState {\n /** True while the canvas is waiting for the designer to click an element. */\n isPicking: boolean\n /** Optional prompt for the picking banner. */\n hint?: string\n}\n\nconst state = observable<PickState>({ isPicking: false, hint: undefined })\n\n// Handler refs live outside the observable — they are plain callbacks, not\n// reactive state, and must not be wrapped by MobX.\nlet onPicked: PickHandler | null = null\nlet onCancel: (() => void) | null = null\nlet escapeListener: ((event: KeyboardEvent) => void) | null = null\n\n/** Reactive: true while a pick is in progress (read from canvas observers). */\nexport function isPicking(): boolean {\n return state.isPicking\n}\n\n/** Reactive: the current picking banner prompt, if any. */\nexport function getHint(): string | undefined {\n return state.hint\n}\n\n/**\n * Enters pick mode. The next canvas leaf click resolves to\n * `handler(nodeId, label)`; Escape (or {@link cancelPick}) aborts and runs\n * `options.onCancel`. Starting a new pick supersedes any in-flight one.\n */\nexport function startPick(\n handler: PickHandler,\n options: StartPickOptions = {},\n): void {\n teardownEscape()\n onPicked = handler\n onCancel = options.onCancel ?? null\n runInAction(() => {\n state.isPicking = true\n state.hint = options.hint\n })\n if (typeof window !== 'undefined') {\n escapeListener = (event: KeyboardEvent) => {\n if (event.key !== 'Escape') return\n // Pick mode only MINIMIZES the interaction builder — the whole\n // besigner (attributes panel, custom-CSS field, raw JSON editor,\n // inline editors) stays live underneath. A capture-phase Escape that\n // ignores focus therefore steals the keystroke a field owns: closing\n // a Select/Autocomplete popper, reverting an inline text edit, or\n // dismissing Monaco's find widget. Text entry wins; the banner's\n // Cancel button, and Escape once focus leaves the field, still abort\n // the pick (AGL-2212).\n if (isTextEntryElement(event.target) || isTextEntryFocused()) return\n event.preventDefault()\n event.stopPropagation()\n cancelPick()\n }\n // Capture phase so the canvas/dialog can't swallow the abort first.\n window.addEventListener('keydown', escapeListener, true)\n }\n}\n\n/** Aborts the current pick and notifies the caller's `onCancel`. */\nexport function cancelPick(): void {\n if (!state.isPicking && !onPicked) return\n const cancel = onCancel\n teardown()\n cancel?.()\n}\n\n/**\n * Canvas-side entry point: the leaf that was clicked while picking hands us\n * its node id. Resolves a human label, exits pick mode, then fires the\n * dialog's callback. No-ops when not picking so a stray click is harmless.\n */\nexport function handlePickClick(nodeId: string): void {\n if (!state.isPicking) return\n const handler = onPicked\n const label = nodeElementLabel(nodeId)\n teardown()\n handler?.(nodeId, label)\n}\n\nfunction teardown(): void {\n onPicked = null\n onCancel = null\n teardownEscape()\n runInAction(() => {\n state.isPicking = false\n state.hint = undefined\n })\n}\n\nfunction teardownEscape(): void {\n if (escapeListener && typeof window !== 'undefined') {\n window.removeEventListener('keydown', escapeListener, true)\n }\n escapeListener = null\n}\n\n/**\n * A friendly, human-readable label for a canvas node — its component's\n * display name, the first string child in quotes when present, and the raw\n * componentId in parentheses (e.g. `Dropdown \"Shop\" (muiNavMenu)`). Shared\n * by the picker callback and the dialog's target chip so both read the same.\n */\nexport function nodeElementLabel(nodeId: string): string {\n const node = canvas.getNode(nodeId as Aglyn.NodeId) as\n { componentId?: string; props?: { children?: unknown } } | undefined\n const componentId = String(node?.componentId ?? '')\n const displayName =\n components.getSchema(componentId as Aglyn.ComponentId)?.displayName ||\n componentId ||\n 'Element'\n const rawChildren = node?.props?.children\n const text =\n typeof rawChildren === 'string' ? rawChildren.trim().slice(0, 24) : ''\n const suffix =\n componentId && componentId !== displayName ? ` (${componentId})` : ''\n return `${displayName}${text ? ` \"${text}\"` : ''}${suffix}`\n}\n"],"names":["canvas","components","observable","runInAction","isTextEntryElement","isTextEntryFocused","state","isPicking","hint","undefined","onPicked","onCancel","escapeListener","getHint","startPick","handler","options","teardownEscape","window","event","key","target","preventDefault","stopPropagation","cancelPick","addEventListener","cancel","teardown","handlePickClick","nodeId","label","nodeElementLabel","removeEventListener","node","getNode","componentId","String","displayName","getSchema","rawChildren","props","children","text","trim","slice","suffix"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAGD,SAASA,MAAM,EAAEC,UAAU,QAAQ,eAAc;AACjD,SAASC,UAAU,EAAEC,WAAW,QAAQ,OAAM;AAC9C,SAASC,kBAAkB,EAAEC,kBAAkB,QAAQ,yBAAe;AAkCtE,MAAMC,QAAQJ,WAAsB;IAAEK,WAAW;IAAOC,MAAMC;AAAU;AAExE,2EAA2E;AAC3E,mDAAmD;AACnD,IAAIC,WAA+B;AACnC,IAAIC,WAAgC;AACpC,IAAIC,iBAA0D;AAE9D,6EAA6E,GAC7E,OAAO,SAASL;IACd,OAAOD,MAAMC,SAAS;AACxB;AAEA,yDAAyD,GACzD,OAAO,SAASM;IACd,OAAOP,MAAME,IAAI;AACnB;AAEA;;;;CAIC,GACD,OAAO,SAASM,UACdC,OAAoB,EACpBC,UAA4B,CAAC,CAAC;QAInBA;IAFXC;IACAP,WAAWK;IACXJ,YAAWK,oBAAAA,QAAQL,QAAQ,YAAhBK,oBAAoB;IAC/Bb,YAAY;QACVG,MAAMC,SAAS,GAAG;QAClBD,MAAME,IAAI,GAAGQ,QAAQR,IAAI;IAC3B;IACA,IAAI,OAAOU,WAAW,aAAa;QACjCN,iBAAiB,CAACO;YAChB,IAAIA,MAAMC,GAAG,KAAK,UAAU;YAC5B,+DAA+D;YAC/D,iEAAiE;YACjE,qEAAqE;YACrE,qEAAqE;YACrE,kEAAkE;YAClE,iEAAiE;YACjE,qEAAqE;YACrE,uBAAuB;YACvB,IAAIhB,mBAAmBe,MAAME,MAAM,KAAKhB,sBAAsB;YAC9Dc,MAAMG,cAAc;YACpBH,MAAMI,eAAe;YACrBC;QACF;QACA,oEAAoE;QACpEN,OAAOO,gBAAgB,CAAC,WAAWb,gBAAgB;IACrD;AACF;AAEA,kEAAkE,GAClE,OAAO,SAASY;IACd,IAAI,CAAClB,MAAMC,SAAS,IAAI,CAACG,UAAU;IACnC,MAAMgB,SAASf;IACfgB;IACAD,0BAAAA;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASE,gBAAgBC,MAAc;IAC5C,IAAI,CAACvB,MAAMC,SAAS,EAAE;IACtB,MAAMQ,UAAUL;IAChB,MAAMoB,QAAQC,iBAAiBF;IAC/BF;IACAZ,2BAAAA,QAAUc,QAAQC;AACpB;AAEA,SAASH;IACPjB,WAAW;IACXC,WAAW;IACXM;IACAd,YAAY;QACVG,MAAMC,SAAS,GAAG;QAClBD,MAAME,IAAI,GAAGC;IACf;AACF;AAEA,SAASQ;IACP,IAAIL,kBAAkB,OAAOM,WAAW,aAAa;QACnDA,OAAOc,mBAAmB,CAAC,WAAWpB,gBAAgB;IACxD;IACAA,iBAAiB;AACnB;AAEA;;;;;CAKC,GACD,OAAO,SAASmB,iBAAiBF,MAAc;;QAK3C5B,uBAGkBgC;IAPpB,MAAMA,OAAOjC,OAAOkC,OAAO,CAACL;IAE5B,MAAMM,cAAcC,eAAOH,wBAAAA,KAAME,WAAW,mBAAI;IAChD,MAAME,cACJpC,EAAAA,wBAAAA,WAAWqC,SAAS,CAACH,iCAArBlC,sBAAwDoC,WAAW,KACnEF,eACA;IACF,MAAMI,cAAcN,yBAAAA,cAAAA,KAAMO,KAAK,qBAAXP,YAAaQ,QAAQ;IACzC,MAAMC,OACJ,OAAOH,gBAAgB,WAAWA,YAAYI,IAAI,GAAGC,KAAK,CAAC,GAAG,MAAM;IACtE,MAAMC,SACJV,eAAeA,gBAAgBE,cAAc,CAAC,EAAE,EAAEF,YAAY,CAAC,CAAC,GAAG;IACrE,OAAO,GAAGE,cAAcK,OAAO,CAAC,EAAE,EAAEA,KAAK,CAAC,CAAC,GAAG,KAAKG,QAAQ;AAC7D"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ export { TEXT_ENTRY_HOST_SELECTOR, isTextEntryElement, isTextEntryFocused, } from './text-entry';
@@ -0,0 +1,18 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2026 Aglyn LLC
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */ export { TEXT_ENTRY_HOST_SELECTOR, isTextEntryElement, isTextEntryFocused } from "./text-entry.js";
17
+
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../../../libs/besigner/core/src/lib/text-entry/index.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nexport {\n TEXT_ENTRY_HOST_SELECTOR,\n isTextEntryElement,\n isTextEntryFocused,\n} from './text-entry'\n"],"names":["TEXT_ENTRY_HOST_SELECTOR","isTextEntryElement","isTextEntryFocused"],"mappings":"AAAA;;;;;;;;;;;;;;;CAeC,GAED,SACEA,wBAAwB,EACxBC,kBAAkB,EAClBC,kBAAkB,QACb,kBAAc"}