@geometra/core 0.2.1 → 0.3.2

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.
package/README.md CHANGED
@@ -37,6 +37,21 @@ const app = createApp(() =>
37
37
  )
38
38
  ```
39
39
 
40
+ ## Text input contract
41
+
42
+ - `TextInputState` is immutable editor state: `{ nodes: string[], selection }`.
43
+ - `selection` is node-local and may be reversed; helpers normalize internally.
44
+ - `insertInputText`/`replaceInputSelection` always collapse caret after replacement.
45
+ - `backspaceInput`/`deleteInput` delete active selections first, then apply boundary merge behavior across nodes.
46
+ - `moveInputCaret` supports range extension via `extendSelection=true`.
47
+ - `getInputCaretGeometry` is defined for collapsed selections with measured line metrics; expanded ranges return `null`.
48
+
49
+ ## Accessibility guarantees and limits
50
+
51
+ - `toAccessibilityTree(tree, layout)` emits deterministic role/name/bounds/focusable nodes for geometry-rendered UIs.
52
+ - Semantic overrides (`semantic.tag`, `semantic.role`, `semantic.ariaLabel`, `semantic.alt`) are preserved when projecting accessibility and semantic HTML output.
53
+ - The core package does not directly expose native accessibility APIs; renderer integrations (for example canvas mirror strategies) are responsible for host-level assistive technology bridging.
54
+
40
55
  ## Links
41
56
 
42
57
  - [Main repo](https://github.com/AiGeekz/geometra)
@@ -1 +1 @@
1
- {"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../src/a11y.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAyC,MAAM,YAAY,CAAA;AAElF,MAAM,WAAW,mBAAmB;IAClC,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,mBAAmB,CAAA;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,QAAQ,EAAE,iBAAiB,EAAE,CAAA;IAC7B,SAAS,EAAE,OAAO,CAAA;CACnB;AA8ED,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,iBAAiB,CAE9F"}
1
+ {"version":3,"file":"a11y.d.ts","sourceRoot":"","sources":["../src/a11y.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAyC,MAAM,YAAY,CAAA;AAElF,MAAM,WAAW,mBAAmB;IAClC,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,mBAAmB,CAAA;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,QAAQ,EAAE,iBAAiB,EAAE,CAAA;IAC7B,SAAS,EAAE,OAAO,CAAA;CACnB;AAqFD,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,iBAAiB,CAE9F"}
package/dist/a11y.js CHANGED
@@ -16,6 +16,20 @@ function inferBoxRole(element) {
16
16
  return 'main';
17
17
  if (tag === 'article')
18
18
  return 'article';
19
+ if (tag === 'section')
20
+ return 'region';
21
+ if (tag === 'ul' || tag === 'ol')
22
+ return 'list';
23
+ if (tag === 'li')
24
+ return 'listitem';
25
+ if (tag === 'form')
26
+ return 'form';
27
+ if (tag === 'label')
28
+ return 'label';
29
+ if (tag === 'button')
30
+ return 'button';
31
+ if (tag === 'input')
32
+ return 'textbox';
19
33
  if (element.handlers?.onClick)
20
34
  return 'button';
21
35
  return 'group';
package/dist/a11y.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"a11y.js","sourceRoot":"","sources":["../src/a11y.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"a11y.js","sourceRoot":"","sources":["../src/a11y.ts"],"names":[],"mappings":"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"}
package/dist/focus.d.ts CHANGED
@@ -4,6 +4,7 @@ import type { Signal } from './signals.js';
4
4
  interface FocusTarget {
5
5
  element: BoxElement;
6
6
  layout: ComputedLayout;
7
+ focusIndex?: number;
7
8
  }
8
9
  /** Signal tracking the currently focused element. */
9
10
  export declare const focusedElement: Signal<FocusTarget | null>;
@@ -1 +1 @@
1
- {"version":3,"file":"focus.d.ts","sourceRoot":"","sources":["../src/focus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,UAAU,WAAW;IACnB,OAAO,EAAE,UAAU,CAAA;IACnB,MAAM,EAAE,cAAc,CAAA;CACvB;AAED,qDAAqD;AACrD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,WAAW,GAAG,IAAI,CAAoC,CAAA;AAE1F,+BAA+B;AAC/B,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAE1E;AAED,+BAA+B;AAC/B,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AA4BD,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAcvE;AAED,oDAAoD;AACpD,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAcvE"}
1
+ {"version":3,"file":"focus.d.ts","sourceRoot":"","sources":["../src/focus.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,UAAU,WAAW;IACnB,OAAO,EAAE,UAAU,CAAA;IACnB,MAAM,EAAE,cAAc,CAAA;IACtB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qDAAqD;AACrD,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,WAAW,GAAG,IAAI,CAAoC,CAAA;AAE1F,+BAA+B;AAC/B,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAE1E;AAED,+BAA+B;AAC/B,wBAAgB,UAAU,IAAI,IAAI,CAEjC;AAsCD,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAgBvE;AAED,oDAAoD;AACpD,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAiBvE"}
package/dist/focus.js CHANGED
@@ -28,6 +28,15 @@ function collectFocusable(element, layout, results) {
28
28
  }
29
29
  }
30
30
  }
31
+ function sameBounds(a, b) {
32
+ return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height;
33
+ }
34
+ function findTargetIndex(targets, current) {
35
+ const byIdentity = targets.findIndex(t => t.element === current.element);
36
+ if (byIdentity !== -1)
37
+ return byIdentity;
38
+ return targets.findIndex(t => sameBounds(t.layout, current.layout));
39
+ }
31
40
  /** Move focus to the next focusable element. */
32
41
  export function focusNext(tree, layout) {
33
42
  const targets = [];
@@ -36,12 +45,14 @@ export function focusNext(tree, layout) {
36
45
  return;
37
46
  const current = focusedElement.peek();
38
47
  if (!current) {
39
- focusedElement.set(targets[0]);
48
+ focusedElement.set({ ...targets[0], focusIndex: 0 });
40
49
  return;
41
50
  }
42
- const idx = targets.findIndex(t => t.element === current.element);
43
- const next = targets[(idx + 1) % targets.length];
44
- focusedElement.set(next);
51
+ const idx = current.focusIndex ?? findTargetIndex(targets, current);
52
+ const safeIdx = idx >= 0 ? idx : 0;
53
+ const nextIndex = (safeIdx + 1) % targets.length;
54
+ const next = targets[nextIndex];
55
+ focusedElement.set({ ...next, focusIndex: nextIndex });
45
56
  }
46
57
  /** Move focus to the previous focusable element. */
47
58
  export function focusPrev(tree, layout) {
@@ -51,11 +62,14 @@ export function focusPrev(tree, layout) {
51
62
  return;
52
63
  const current = focusedElement.peek();
53
64
  if (!current) {
54
- focusedElement.set(targets[targets.length - 1]);
65
+ const lastIndex = targets.length - 1;
66
+ focusedElement.set({ ...targets[lastIndex], focusIndex: lastIndex });
55
67
  return;
56
68
  }
57
- const idx = targets.findIndex(t => t.element === current.element);
58
- const prev = targets[(idx - 1 + targets.length) % targets.length];
59
- focusedElement.set(prev);
69
+ const idx = current.focusIndex ?? findTargetIndex(targets, current);
70
+ const safeIdx = idx >= 0 ? idx : 0;
71
+ const prevIndex = (safeIdx - 1 + targets.length) % targets.length;
72
+ const prev = targets[prevIndex];
73
+ focusedElement.set({ ...prev, focusIndex: prevIndex });
60
74
  }
61
75
  //# sourceMappingURL=focus.js.map
package/dist/focus.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"focus.js","sourceRoot":"","sources":["../src/focus.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"focus.js","sourceRoot":"","sources":["../src/focus.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAGlF;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,WAAW,GAAG,SAAS,EAClC,YAAY,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAC7C,OAAO,CA+BT;AAED,8DAA8D;AAC9D,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,oBAAoB,GAAG,qBAAqB,GAAG,kBAAkB,EAC5E,YAAY,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,GAChD,OAAO,CAQT"}
1
+ {"version":3,"file":"keyboard.d.ts","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAA;AAGlF;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,SAAS,EACf,MAAM,EAAE,cAAc,EACtB,SAAS,EAAE,WAAW,GAAG,SAAS,EAClC,YAAY,EAAE,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,GAC7C,OAAO,CAqBT;AAED,8DAA8D;AAC9D,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,cAAc,EACvB,SAAS,EAAE,oBAAoB,GAAG,qBAAqB,GAAG,kBAAkB,EAC5E,YAAY,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,GAChD,OAAO,CAQT"}
package/dist/keyboard.js CHANGED
@@ -4,26 +4,7 @@ import { focusedElement, focusNext, focusPrev } from './focus.js';
4
4
  * Also handles Tab/Shift+Tab focus traversal.
5
5
  */
6
6
  export function dispatchKeyboardEvent(tree, layout, eventType, partialEvent) {
7
- const focused = focusedElement.peek();
8
- if (!focused) {
9
- if (partialEvent.key === 'Tab') {
10
- if (partialEvent.shiftKey) {
11
- focusPrev(tree, layout);
12
- }
13
- else {
14
- focusNext(tree, layout);
15
- }
16
- return true;
17
- }
18
- return false;
19
- }
20
- const handler = focused.element.handlers?.[eventType];
21
- if (handler) {
22
- const event = { ...partialEvent, target: focused.layout };
23
- handler(event);
24
- return true;
25
- }
26
- if (partialEvent.key === 'Tab') {
7
+ if (partialEvent.key === 'Tab' && eventType === 'onKeyDown') {
27
8
  if (partialEvent.shiftKey) {
28
9
  focusPrev(tree, layout);
29
10
  }
@@ -32,6 +13,15 @@ export function dispatchKeyboardEvent(tree, layout, eventType, partialEvent) {
32
13
  }
33
14
  return true;
34
15
  }
16
+ const focused = focusedElement.peek();
17
+ if (!focused)
18
+ return false;
19
+ const handler = focused.element.handlers?.[eventType];
20
+ if (handler) {
21
+ const event = { ...partialEvent, target: focused.layout };
22
+ handler(event);
23
+ return true;
24
+ }
35
25
  return false;
36
26
  }
37
27
  /** Dispatch IME composition events to the focused element. */
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEjE;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAe,EACf,MAAsB,EACtB,SAAkC,EAClC,YAA8C;IAE9C,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,CAAA;IACrC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,IAAI,YAAY,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;YAC/B,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;gBAC1B,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YACzB,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YACzB,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAA;IACrD,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,KAAK,GAAqB,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAA;QAC3E,OAAO,CAAC,KAAK,CAAC,CAAA;QACd,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,YAAY,CAAC,GAAG,KAAK,KAAK,EAAE,CAAC;QAC/B,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC1B,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzB,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,wBAAwB,CACtC,KAAgB,EAChB,OAAuB,EACvB,SAA4E,EAC5E,YAAiD;IAEjD,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,CAAA;IACrC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAA;IACrD,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,MAAM,KAAK,GAAwB,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAA;IAC9E,OAAO,CAAC,KAAK,CAAC,CAAA;IACd,OAAO,IAAI,CAAA;AACb,CAAC"}
1
+ {"version":3,"file":"keyboard.js","sourceRoot":"","sources":["../src/keyboard.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEjE;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,IAAe,EACf,MAAsB,EACtB,SAAkC,EAClC,YAA8C;IAE9C,IAAI,YAAY,CAAC,GAAG,KAAK,KAAK,IAAI,SAAS,KAAK,WAAW,EAAE,CAAC;QAC5D,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC1B,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzB,CAAC;aAAM,CAAC;YACN,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACzB,CAAC;QACD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,CAAA;IACrC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAE1B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAA;IACrD,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,KAAK,GAAqB,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAA;QAC3E,OAAO,CAAC,KAAK,CAAC,CAAA;QACd,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,wBAAwB,CACtC,KAAgB,EAChB,OAAuB,EACvB,SAA4E,EAC5E,YAAiD;IAEjD,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,EAAE,CAAA;IACrC,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,CAAA;IACrD,IAAI,CAAC,OAAO;QAAE,OAAO,KAAK,CAAA;IAC1B,MAAM,KAAK,GAAwB,EAAE,GAAG,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAA;IAC9E,OAAO,CAAC,KAAK,CAAC,CAAA;IACd,OAAO,IAAI,CAAA;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geometra/core",
3
- "version": "0.2.1",
3
+ "version": "0.3.2",
4
4
  "description": "DOM-free UI framework core: components, signals, reconciler",
5
5
  "license": "MIT",
6
6
  "type": "module",