native-document 1.0.169 → 1.0.172

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 (123) hide show
  1. package/CHANGELOG.md +62 -1
  2. package/docs/vitepress-conventions.md +2 -2
  3. package/package.json +11 -4
  4. package/src/components/BaseComponent.js +43 -1
  5. package/src/components/accordion/Accordion.js +1 -0
  6. package/src/components/accordion/AccordionItem.js +1 -0
  7. package/src/components/alert/Alert.js +4 -0
  8. package/src/components/avatar/Avatar.js +1 -0
  9. package/src/components/avatar/AvatarGroup.js +1 -0
  10. package/src/components/badge/Badge.js +1 -0
  11. package/src/components/breadcrumb/BreadCrumb.js +4 -0
  12. package/src/components/button/Button.js +1 -0
  13. package/src/components/card/Card.js +1 -0
  14. package/src/components/context-menu/ContextMenu.js +2 -0
  15. package/src/components/context-menu/ContextMenuGroup.js +2 -0
  16. package/src/components/context-menu/ContextMenuItem.js +2 -0
  17. package/src/components/divider/Divider.js +2 -0
  18. package/src/components/dropdown/Dropdown.js +1 -0
  19. package/src/components/dropdown/DropdownDivider.js +1 -0
  20. package/src/components/dropdown/DropdownGroup.js +1 -0
  21. package/src/components/dropdown/DropdownItem.js +1 -0
  22. package/src/components/dropdown/DropdownTrigger.js +1 -0
  23. package/src/components/form/FormControl.js +1 -0
  24. package/src/components/form/field/Field.js +1 -0
  25. package/src/components/form/field/types/StringField.js +1 -1
  26. package/src/components/icon/Icon.js +1 -0
  27. package/src/components/list/ListItem.js +1 -0
  28. package/src/components/menu/Menu.js +3 -0
  29. package/src/components/menu/MenuDivider.js +1 -0
  30. package/src/components/menu/MenuGroup.js +1 -0
  31. package/src/components/menu/MenuItem.js +1 -0
  32. package/src/components/menu/MenuLink.js +1 -0
  33. package/src/components/modal/Modal.js +4 -0
  34. package/src/components/pagination/Pagination.js +1 -0
  35. package/src/components/popover/Popover.js +1 -0
  36. package/src/components/popover/PopoverFooter.js +1 -0
  37. package/src/components/popover/PopoverHeader.js +1 -0
  38. package/src/components/progress/Progress.js +5 -0
  39. package/src/components/skeleton/Skeleton.js +4 -0
  40. package/src/components/slider/Slider.js +1 -0
  41. package/src/components/spacer/Spacer.js +1 -0
  42. package/src/components/spinner/Spinner.js +1 -0
  43. package/src/components/splitter/Splitter.js +1 -0
  44. package/src/components/splitter/SplitterGutter.js +6 -0
  45. package/src/components/splitter/SplitterPanel.js +1 -0
  46. package/src/components/stacks/AbsoluteStack.js +1 -0
  47. package/src/components/stacks/FixedStack.js +1 -0
  48. package/src/components/stacks/HStack.js +1 -0
  49. package/src/components/stacks/PositionStack.js +1 -0
  50. package/src/components/stacks/RelativeStack.js +1 -0
  51. package/src/components/stacks/Stack.js +1 -0
  52. package/src/components/stacks/VStack.js +1 -0
  53. package/src/components/stepper/Stepper.js +1 -0
  54. package/src/components/stepper/StepperStep.js +1 -0
  55. package/src/components/switch/Switch.js +1 -0
  56. package/src/components/table/DataTable.js +1 -0
  57. package/src/components/table/SimpleTable.js +1 -0
  58. package/src/components/tabs/Tabs.js +1 -0
  59. package/src/components/toast/Toast.js +1 -0
  60. package/src/components/tooltip/Tooltip.js +1 -0
  61. package/src/core/data/MemoryManager.js +6 -1
  62. package/src/core/data/ObservableItem.js +28 -10
  63. package/src/core/elements/anchor/anchor.js +4 -3
  64. package/src/core/elements/anchor/one-child-anchor-overwriting.js +4 -4
  65. package/src/core/elements/content-formatter.js +19 -0
  66. package/src/core/elements/control/for-each-array-cache.js +59 -0
  67. package/src/core/elements/control/for-each-array.js +15 -23
  68. package/src/core/wrappers/AttributesWrapper.js +12 -12
  69. package/src/core/wrappers/ElementCreator.js +33 -10
  70. package/src/core/wrappers/HtmlElementWrapper.js +9 -4
  71. package/src/core/wrappers/NDElement.js +23 -8
  72. package/src/core/wrappers/NdPrototype.js +31 -39
  73. package/src/core/wrappers/constants.js +12 -12
  74. package/src/core/wrappers/prototypes/nd-element-extensions.js +127 -57
  75. package/src/ui/components/accordion/AccordionItemRender.js +29 -7
  76. package/src/ui/components/alert/AlertRender.js +6 -0
  77. package/src/ui/components/breadcrumb/BreadcrumbRender.js +9 -1
  78. package/src/ui/components/button/ButtonRender.js +3 -0
  79. package/src/ui/components/contextmenu/ContextmenuRender.js +2 -0
  80. package/src/ui/components/dropdown/DropdownRender.js +3 -0
  81. package/src/ui/components/dropdown/item/DropdownItemRender.js +6 -1
  82. package/src/ui/components/form/FieldCollectionRender.js +4 -0
  83. package/src/ui/components/form/fields/CheckboxFieldRender.js +4 -0
  84. package/src/ui/components/form/fields/CheckboxGroupFieldRender.js +4 -0
  85. package/src/ui/components/form/fields/RadioFieldRender.js +4 -0
  86. package/src/ui/components/form/fields/RangeFieldRender.js +4 -0
  87. package/src/ui/components/form/fields/SelectFieldRender.js +5 -0
  88. package/src/ui/components/form/fields/SliderFieldRender.js +3 -0
  89. package/src/ui/components/icon/tabler/TablerIconRender.js +0 -1
  90. package/src/ui/components/list/item/ListItemRender.js +4 -0
  91. package/src/ui/components/menu/MenuItemRender.js +8 -0
  92. package/src/ui/components/menu/MenuLinkRender.js +11 -0
  93. package/src/ui/components/menu/MenuRender.js +5 -0
  94. package/src/ui/components/menu/helpers.js +2 -1
  95. package/src/ui/components/modal/ModalRender.js +8 -2
  96. package/src/ui/components/progress/ProgressRender.js +9 -0
  97. package/src/ui/components/skeleton/SkeletonRender.js +2 -0
  98. package/src/ui/components/spinner/SpinnerRender.js +3 -0
  99. package/src/ui/components/splitter/SplitterGutterRender.js +4 -0
  100. package/src/ui/components/splitter/SplitterPanelRender.js +4 -0
  101. package/src/ui/components/splitter/SplitterRender.js +2 -0
  102. package/src/ui/components/stepper/StepperRender.js +2 -1
  103. package/src/ui/components/stepper/StepperStepRender.js +8 -1
  104. package/src/ui/components/switch/SwitchRender.js +3 -0
  105. package/src/ui/components/table/data-table/DataTableRender.js +4 -0
  106. package/src/ui/components/table/simple-table/SimpleTableRender.js +2 -0
  107. package/src/ui/components/toast/ToastRender.js +4 -0
  108. package/src/ui/utils/aria.js +19 -0
  109. package/tests/integration/ui/attributes-wrapper.test.js +177 -0
  110. package/tests/integration/ui/for-each-array.test.js +167 -0
  111. package/tests/integration/ui/lifecycle.test.js +146 -0
  112. package/tests/integration/ui/show-if.test.js +168 -0
  113. package/tests/unit/core/observable-array.test.js +404 -0
  114. package/tests/unit/core/observable-item.test.js +428 -0
  115. package/tests/unit/core/observable-object.test.js +239 -0
  116. package/tests/unit/core/observable-resource.test.js +323 -0
  117. package/tests/unit/core/store.test.js +347 -0
  118. package/tests/unit/router/route-matching.test.js +169 -0
  119. package/tests/unit/router/router-guards.test.js +189 -0
  120. package/tests/unit/utils/cache.test.js +120 -0
  121. package/tests/unit/utils/filters.test.js +394 -0
  122. package/types/elements.d.ts +5 -0
  123. package/vitest.config.js +15 -0
package/CHANGELOG.md CHANGED
@@ -11,6 +11,65 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ---
13
13
 
14
+ ## [1.0.172] - 2026-06-15
15
+
16
+ ### Added
17
+
18
+ - `Text(string)` — shorthand for `string.toNdChildren()`, parses Observable placeholders in template strings
19
+ - `String.prototype.toNdChildren()` — splits a string containing `{{obs:N}}` placeholders into a mixed array of strings and resolved Observables
20
+ - `ObservableItem.prototype.toString()` — auto-registers the Observable in MemoryManager and returns `{{obs:id}}`, enabling reactive interpolation via standard template literals
21
+ - `NDElement.prototype.className(classes)` — adds static classes, bypasses AttributesWrapper
22
+ - `NDElement.prototype.class(className, value)` — adds a reactive class binding, bypasses AttributesWrapper
23
+ - `__$isNativeNode` flag on DOM prototypes (`Element`, `Text`, `Comment`, `Document`, `DocumentFragment`) — faster alternative to `instanceof Node`
24
+ - `__$isValidNdChild` flag on all valid NdChild prototypes — single property check replaces multiple type guards
25
+ - `defineToNdElement`, `defineValidNdChild`, `defineNativeNode` — non-enumerable prototype helpers in `nd-element-extensions`
26
+ - camelCase variants added to `BOOLEAN_ATTRIBUTES` — removes `toLowerCase()` call on each attribute in the hot path
27
+
28
+ ### Changed
29
+
30
+ - `ElementCreator.processChildren` and `getChild` — refactored for better performance
31
+ - `nd-element-extensions` — all prototype extensions converted to non-enumerable `defineProperty`
32
+ - `AttributesWrapper` — `options` defaults to `null` instead of `{}`, fixes truthy check issue
33
+ - NDElement events — inline handler (`on*`) used when no existing handler and no options; falls back to `addEventListener` for subsequent handlers or when options are provided
34
+ - `_prevent`, `_stop`, `_preventStop` — updated with same inline handler strategy
35
+
36
+ ---
37
+
38
+ ## [1.0.170] - 2026-06-10
39
+
40
+ ### Added
41
+
42
+ - Vitest test suite — `vitest.config.js`, happy-dom environment, scripts `test`, `test:watch`, `test:ui`, `test:coverage`
43
+ - 372 tests passing across 13 files — 0 failures, 0 todo
44
+
45
+ #### Unit tests — core
46
+ - `observable-item` — 48 cases: set, val, subscribe, on/off, once, toggle, reset, transform, equals, clone, cleanup, intercept, assocTrigger
47
+ - `observable-array` — 48 cases: push, remove, clear, merge, swap, insertAfter, isIncludes, where, sync, clone, reset, deepSubscribe
48
+ - `observable-object` — 30 cases: constructor, val, get, set, subscribe, keys, observables, reset, clone
49
+ - `observable-resource` — 29 cases: states, fetch, refetch, mutate, abort, race condition, deps, onSuccess, onError, into, apply, destroy
50
+ - `store` — 43 cases: create, createResettable, createComposed, use, follow, reset, delete, group, protected, createPersistent
51
+
52
+ #### Unit tests — router
53
+ - `route-matching` — 26 cases: exact path, params, typed params, custom validators, url(), metadata
54
+ - `router-guards` — 14 cases: middleware execution, group middlewares, subscribe, resolve, currentState
55
+
56
+ #### Unit tests — utils
57
+ - `cache` — 12 cases: singleton, once, memoize
58
+ - `filters` — 60 cases: equals, comparison, inArray, isEmpty, match, and/or/not, custom, string filters, date/time filters
59
+
60
+ #### Integration tests — UI
61
+ - `attributes-wrapper` — 22 cases: string, class map, style, Observable, boolean, aria attributes
62
+ - `show-if` — 16 cases: static boolean, observable, factory child, HideIf, HideIfNot
63
+ - `for-each-array` — 13 cases: static array, push, removeItem, clear, set, swap, index observable, order preservation
64
+ - `lifecycle` — 11 cases: mounted, unmounted, destroy, destroyOnUnmount
65
+
66
+ ### Fixed
67
+
68
+ - `NDElement.prototype.destroy()` — guard against double call when `$element` is already null
69
+ - `NDElement.prototype.destroy()` — disconnect lifecycle observer to prevent callbacks from firing after destroy
70
+
71
+ ---
72
+
14
73
  ## [1.0.169] - 2026-06-06
15
74
 
16
75
  ### Added
@@ -181,7 +240,9 @@ Entries use the following categories:
181
240
 
182
241
  ---
183
242
 
184
- [Unreleased]: https://github.com/afrocodeur/native-document/compare/v1.0.169...HEAD
243
+ [Unreleased]: https://github.com/afrocodeur/native-document/compare/v1.0.172...HEAD
244
+ [1.0.172]: https://github.com/afrocodeur/native-document/compare/v1.0.170...v1.0.172
245
+ [1.0.170]: https://github.com/afrocodeur/native-document/compare/v1.0.169...v1.0.170
185
246
  [1.0.169]: https://github.com/afrocodeur/native-document/compare/v1.0.167...v1.0.169
186
247
  [1.0.167]: https://github.com/afrocodeur/native-document/compare/v1.0.166...v1.0.167
187
248
  [1.0.166]: https://github.com/afrocodeur/native-document/releases/tag/v1.0.166
@@ -75,7 +75,7 @@ docs/
75
75
  ## Internal Links
76
76
 
77
77
  VitePress resolves links relative to the current file.
78
- Always use `.md` extension VitePress strips it at build time.
78
+ Always use `.md` extension - VitePress strips it at build time.
79
79
 
80
80
  ```markdown
81
81
  <!-- From docs/readme.md or docs/getting-started.md -->
@@ -93,7 +93,7 @@ Never use absolute paths (`/docs/...`) or paths without `.md`.
93
93
 
94
94
  ---
95
95
 
96
- ## `.vitepress/config.js` Sidebar & Nav
96
+ ## `.vitepress/config.js` - Sidebar & Nav
97
97
 
98
98
  ```javascript
99
99
  // .vitepress/config.js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "native-document",
3
- "version": "1.0.169",
3
+ "version": "1.0.172",
4
4
  "description": "A reactive JavaScript framework that preserves native DOM simplicity without sacrificing modern features",
5
5
  "author": "AfroCodeur <https://github.com/afrocodeur>",
6
6
  "license": "MIT",
@@ -41,7 +41,11 @@
41
41
  "build": "rollup --config rollup.config.js",
42
42
  "build:watch": "rollup --config rollup.config.js --watch",
43
43
  "lint": "eslint ./src",
44
- "lint:fix": "eslint ./src --fix"
44
+ "lint:fix": "eslint ./src --fix",
45
+ "test": "vitest run",
46
+ "test:watch": "vitest",
47
+ "test:ui": "vitest --ui",
48
+ "test:coverage": "vitest run --coverage"
45
49
  },
46
50
  "dependencies": {
47
51
  "@floating-ui/dom": "^1.7.6",
@@ -53,14 +57,17 @@
53
57
  "@rollup/plugin-alias": "^5.1.1",
54
58
  "@rollup/plugin-replace": "^6.0.2",
55
59
  "@rollup/plugin-terser": "^0.4.4",
60
+ "@vitest/coverage-v8": "^4.1.8",
56
61
  "eslint": "^9.33.0",
57
62
  "eslint-plugin-jsdoc": "^62.5.4",
63
+ "happy-dom": "^20.10.2",
58
64
  "magic-string": "^0.30.21",
59
65
  "postcss": "^8.5.12",
60
66
  "rollup": "^4.53.3",
61
- "rollup-plugin-postcss": "^4.0.2"
67
+ "rollup-plugin-postcss": "^4.0.2",
68
+ "vitest": "^4.1.8"
62
69
  },
63
70
  "engines": {
64
71
  "node": ">=18.0.0"
65
72
  }
66
- }
73
+ }
@@ -181,6 +181,12 @@ BaseComponent.prototype.getEditableProps = function() {
181
181
  class: classPropertyAccumulator(rawProps.class || {}),
182
182
  style: cssPropertyAccumulator(rawProps.style || {}),
183
183
  };
184
+
185
+ if (this.aria) {
186
+ for (const key in this.aria) {
187
+ this.$editableProps[resolveAriaKey(key)] = this.aria[key];
188
+ }
189
+ }
184
190
  }
185
191
 
186
192
  return this.$editableProps;
@@ -244,4 +250,40 @@ BaseComponent.prototype.context = function(context) {
244
250
  return this;
245
251
  };
246
252
 
247
- BaseComponent.prototype.visibility = BaseComponent.prototype.showIf;
253
+ BaseComponent.prototype.visibility = BaseComponent.prototype.showIf;
254
+
255
+ //------------------------------------------------------------------------------
256
+ //--Component Aria -------------------------------------------------------------
257
+ //------------------------------------------------------------------------------
258
+ const ARIA_NO_PREFIX = new Set(['role', 'id', 'tabindex']);
259
+
260
+ /**
261
+ * @param {string} key
262
+ * @returns {string}
263
+ */
264
+ const resolveAriaKey = (key) =>
265
+ ARIA_NO_PREFIX.has(key) || key.startsWith('aria-') ? key : `aria-${key}`;
266
+
267
+ /**
268
+ * Override or extend aria attributes on the root element.
269
+ * Automatically prefixes keys with 'aria-' unless they are in ARIA_NO_PREFIX.
270
+ *
271
+ * @example
272
+ * Modal()
273
+ * .setAria({ label: 'Confirmation dialog' })
274
+ * .setAria({ describedby: 'modal-desc' })
275
+ *
276
+ * @param {Record<string, string|boolean|Observable>} attrs
277
+ * @returns {this}
278
+ */
279
+ BaseComponent.prototype.setAria = function(attrs) {
280
+ if (!this.aria) {
281
+ this.aria = {};
282
+ }
283
+ for (const key in attrs) {
284
+ this.aria[resolveAriaKey(key)] = attrs[key];
285
+ }
286
+ return this;
287
+ };
288
+
289
+
@@ -36,6 +36,7 @@ export default function Accordion(props = {}) {
36
36
  renderIndicator: null,
37
37
  props,
38
38
  };
39
+ this.aria = {};
39
40
  }
40
41
 
41
42
  BaseComponent.extends(Accordion);
@@ -41,6 +41,7 @@ export default function AccordionItem(props = {}) {
41
41
  disabled: $(false),
42
42
  props,
43
43
  };
44
+ this.aria = { 'tabindex': '0' };
44
45
  }
45
46
 
46
47
  BaseComponent.extends(AccordionItem);
@@ -44,6 +44,10 @@ export default function Alert(content, props = {}) {
44
44
  actions: [],
45
45
  props,
46
46
  };
47
+ this.aria = {
48
+ 'role': 'alert',
49
+ 'aria-live': 'assertive'
50
+ };
47
51
  }
48
52
 
49
53
  Alert.defaultTemplate = null;
@@ -42,6 +42,7 @@ export default function Avatar(source, props = {}) {
42
42
  render: null,
43
43
  props,
44
44
  };
45
+ this.aria = { 'role': 'img' };
45
46
  }
46
47
 
47
48
  BaseComponent.extends(Avatar);
@@ -31,6 +31,7 @@ export default function AvatarGroup(props = {}) {
31
31
  props,
32
32
  };
33
33
 
34
+ this.aria = { 'role': 'group' };
34
35
  };
35
36
 
36
37
  BaseComponent.extends(AvatarGroup);
@@ -36,6 +36,7 @@ export default function Badge(content, props = {}) {
36
36
  content,
37
37
  props,
38
38
  };
39
+ this.aria = {};
39
40
  }
40
41
 
41
42
  BaseComponent.extends(Badge);
@@ -21,6 +21,10 @@ export default function Breadcrumb(props = {}) {
21
21
  renderItem: null,
22
22
  props,
23
23
  };
24
+ this.aria = {
25
+ 'role': 'navigation',
26
+ 'aria-label': 'Breadcrumb'
27
+ };
24
28
  }
25
29
 
26
30
  BaseComponent.extends(Breadcrumb);
@@ -55,6 +55,7 @@ export default function Button(label, props = {}) {
55
55
  outline: null,
56
56
  props,
57
57
  };
58
+ this.aria = { 'role': 'button' };
58
59
 
59
60
  this.$element = null;
60
61
  }
@@ -45,6 +45,7 @@ export default function Card(props = {}) {
45
45
  layout: null,
46
46
  props,
47
47
  };
48
+ this.aria = {};
48
49
  }
49
50
 
50
51
  BaseComponent.extends(Card);
@@ -35,6 +35,8 @@ export default function ContextMenu(props = {}) {
35
35
  trigger: null,
36
36
  data: null,
37
37
  });
38
+
39
+ this.aria = { 'role': 'menu' };
38
40
  }
39
41
 
40
42
  BaseComponent.extends(ContextMenu);
@@ -13,6 +13,8 @@ export default function ContextMenuGroup(label, config) {
13
13
  }
14
14
 
15
15
  MenuGroup.call(this, label, config);
16
+
17
+ this.aria = { 'role': 'group' };
16
18
  }
17
19
 
18
20
 
@@ -12,6 +12,8 @@ export default function ContextMenuItem(config) {
12
12
  }
13
13
 
14
14
  MenuItem.call(this, config);
15
+
16
+ this.aria = { 'role': 'menuitem' };
15
17
  }
16
18
 
17
19
 
@@ -41,6 +41,8 @@ export default function Divider(label, props = {}) {
41
41
  trailing: null,
42
42
  props,
43
43
  };
44
+
45
+ this.aria = { 'role': 'separator' };
44
46
  }
45
47
 
46
48
  BaseComponent.extends(Divider);
@@ -66,6 +66,7 @@ export default function Dropdown(props = {}) {
66
66
  includeTriggerIntoGhost: true,
67
67
  props,
68
68
  };
69
+ this.aria = { 'role': 'listbox' };
69
70
  }
70
71
 
71
72
  BaseComponent.extends(Dropdown);
@@ -18,6 +18,7 @@ export default function DropdownDivider(props = {}) {
18
18
  type: 'divider',
19
19
  props,
20
20
  };
21
+ this.aria = { 'role': 'separator' };
21
22
  }
22
23
 
23
24
  BaseComponent.extends(DropdownDivider);
@@ -27,6 +27,7 @@ export default function DropdownGroup(props) {
27
27
  Object.assign(this.$description, {
28
28
  items: $.array([]),
29
29
  });
30
+ this.aria = { 'role': 'group' };
30
31
  }
31
32
 
32
33
  BaseComponent.extends(DropdownGroup, DropdownItem);
@@ -38,6 +38,7 @@ export default function DropdownItem(props = {}) {
38
38
  renderContent: null,
39
39
  props,
40
40
  };
41
+ this.aria = { 'role': 'option', 'tabindex': '-1' };
41
42
  };
42
43
 
43
44
  BaseComponent.extends(DropdownItem);
@@ -26,6 +26,7 @@ export default function DropdownTrigger(config) {
26
26
  isOpen: null,
27
27
  ...config,
28
28
  };
29
+ this.aria = { 'aria-haspopup': 'listbox' };
29
30
  }
30
31
 
31
32
  BaseComponent.extends(DropdownTrigger);
@@ -47,6 +47,7 @@ export default function FormControl(props) {
47
47
  isValid: $(false),
48
48
  props,
49
49
  };
50
+ this.aria = { 'role': 'form' };
50
51
  }
51
52
 
52
53
  FormControl.defaultTemplate = null;
@@ -64,6 +64,7 @@ export default function Field(name, type, props) {
64
64
  slots: {},
65
65
  props,
66
66
  };
67
+ this.aria = { 'role': 'group' };
67
68
 
68
69
  this.$description.errors.intercept((nextValue) => nextValue === null ? [] : nextValue);
69
70
  }
@@ -26,7 +26,7 @@ import {Validation} from '../../validation/Validation';
26
26
  */
27
27
  export default function StringField(name, type = 'text', props = {}) {
28
28
  if(!(this instanceof StringField)) {
29
- return new StringField(name, props);
29
+ return new StringField(name, type, props);
30
30
  }
31
31
 
32
32
  Field.call(this, name, type, props);
@@ -20,6 +20,7 @@ export function Icon(name, props = {}) {
20
20
  size: null,
21
21
  ...props,
22
22
  };
23
+ this.aria = { 'aria-hidden': 'true' };
23
24
  }
24
25
 
25
26
  BaseComponent.extends(Icon);
@@ -49,6 +49,7 @@ export default function ListItem(props = {}) {
49
49
  render: null,
50
50
  props,
51
51
  };
52
+ this.aria = { 'role': 'listitem', 'tabindex': '-1' };
52
53
  }
53
54
 
54
55
  BaseComponent.extends(ListItem);
@@ -53,6 +53,9 @@ export default function Menu(props = {}) {
53
53
  props,
54
54
  };
55
55
 
56
+
57
+ this.aria = { 'role': 'menu' };
58
+
56
59
  }
57
60
 
58
61
  BaseComponent.extends(Menu);
@@ -19,6 +19,7 @@ export default function MenuDivider(props = {}) {
19
19
  this.$description = {
20
20
  props,
21
21
  };
22
+ this.aria = { 'role': 'separator' };
22
23
  }
23
24
 
24
25
  BaseComponent.extends(MenuDivider);
@@ -39,6 +39,7 @@ export default function MenuGroup(label, props = {}) {
39
39
  collapsableClosedIcon: null,
40
40
  props,
41
41
  };
42
+ this.aria = { 'role': 'group' };
42
43
  }
43
44
 
44
45
  HasMenuItem.components.MenuGroup = MenuGroup;
@@ -51,6 +51,7 @@ export default function MenuItem(props = {}) {
51
51
  visibility: null,
52
52
  props,
53
53
  };
54
+ this.aria = { 'role': 'menuitem', 'tabindex': '-1' };
54
55
 
55
56
  }
56
57
 
@@ -21,6 +21,7 @@ export default function MenuLink(props = {}) {
21
21
  return new MenuLink(props);
22
22
  }
23
23
  MenuItem.call(this, props);
24
+ this.aria = { 'role': 'menuitem' };
24
25
  }
25
26
 
26
27
  MenuLink.prototype = Object.create(MenuItem.prototype);
@@ -67,6 +67,10 @@ export default function Modal(content, props = {}) {
67
67
  variant: null,
68
68
  props,
69
69
  };
70
+ this.aria = {
71
+ 'role': 'dialog',
72
+ 'aria-modal': 'true'
73
+ };
70
74
  }
71
75
 
72
76
  BaseComponent.extends(Modal);
@@ -50,6 +50,7 @@ export default function Pagination(props = {}) {
50
50
  render: null,
51
51
  props,
52
52
  };
53
+ this.aria = { 'role': 'navigation', 'aria-label': 'Pagination' };
53
54
 
54
55
  this.$element = null;
55
56
  }
@@ -64,6 +64,7 @@ export default function Popover(content, props = {}) {
64
64
  includeTriggerIntoGhost: true,
65
65
  props,
66
66
  };
67
+ this.aria = { 'role': 'tooltip' };
67
68
 
68
69
  this.$element = null;
69
70
 
@@ -24,6 +24,7 @@ export default function PopoverFooter(content, config = {}) {
24
24
  render: null,
25
25
  ...config,
26
26
  };
27
+ this.aria = { };
27
28
  }
28
29
 
29
30
  BaseComponent.extends(PopoverFooter);
@@ -25,6 +25,7 @@ export default function PopoverHeader(content, config = {}) {
25
25
  render: null,
26
26
  ...config,
27
27
  };
28
+ this.aria = { 'role': 'heading' };
28
29
  }
29
30
 
30
31
  BaseComponent.extends(PopoverHeader);
@@ -50,6 +50,11 @@ export default function Progress(props = {}) {
50
50
  borderRadiusType: null,
51
51
  props,
52
52
  };
53
+ this.aria = {
54
+ 'role': 'progressbar',
55
+ 'aria-valuemin': '0',
56
+ 'aria-valuemax': '100'
57
+ };
53
58
  }
54
59
 
55
60
  BaseComponent.extends(Progress);
@@ -42,6 +42,10 @@ export default function Skeleton(props = {}) {
42
42
  repeat: null,
43
43
  props,
44
44
  };
45
+ this.aria = {
46
+ 'aria-busy': 'true',
47
+ 'aria-live': 'polite'
48
+ };
45
49
  }
46
50
 
47
51
  BaseComponent.extends(Skeleton);
@@ -61,6 +61,7 @@ export default function Slider(name, props = {}) {
61
61
  renderThumb: null,
62
62
  props,
63
63
  };
64
+ this.aria = { 'role': 'slider', 'tabindex': '0' };
64
65
  }
65
66
 
66
67
  Slider.prototype = Object.create(Field.prototype);
@@ -9,6 +9,7 @@ export default function Spacer(props = {}) {
9
9
  type: 'spacer',
10
10
  props,
11
11
  };
12
+ this.aria = { 'aria-hidden': 'true' };
12
13
  }
13
14
  BaseComponent.extends(Spacer);
14
15
 
@@ -42,6 +42,7 @@ export default function Spinner(props = {}) {
42
42
  fullScreenOverlay: null,
43
43
  props,
44
44
  };
45
+ this.aria = { 'role': 'status', 'aria-label': 'Loading' };
45
46
  }
46
47
 
47
48
  Spinner.defaultTemplate = null;
@@ -33,6 +33,7 @@ export default function Splitter(props = {}) {
33
33
  render: null,
34
34
  props,
35
35
  };
36
+ this.aria = { 'role': 'group' };
36
37
 
37
38
  this.$element = null;
38
39
  }
@@ -33,6 +33,10 @@ export default function SplitterGutter(leftPanel, rightPanel, props = {}) {
33
33
  isDragging: $(false),
34
34
  props,
35
35
  };
36
+ this.aria = {
37
+ 'role': 'separator',
38
+ 'aria-orientation': 'horizontal',
39
+ };
36
40
  }
37
41
 
38
42
  BaseComponent.extends(SplitterGutter);
@@ -62,6 +66,7 @@ SplitterGutter.use = function(template) {
62
66
  SplitterGutter.prototype.vertical = function() {
63
67
  this.$description.orientation = 'vertical';
64
68
  this.$description.cursor = 'row-resize';
69
+ this.aria['aria-orientation'] = 'vertical';
65
70
  return this;
66
71
  };
67
72
 
@@ -71,6 +76,7 @@ SplitterGutter.prototype.vertical = function() {
71
76
  SplitterGutter.prototype.horizontal = function() {
72
77
  this.$description.orientation = 'horizontal';
73
78
  this.$description.cursor = 'col-resize';
79
+ this.aria['aria-orientation'] = 'horizontal';
74
80
  return this;
75
81
  };
76
82
 
@@ -37,6 +37,7 @@ export default function SplitterPanel(content, props = {}) {
37
37
  render: null,
38
38
  props,
39
39
  };
40
+ this.aria = { 'role': 'region' };
40
41
  }
41
42
 
42
43
  BaseComponent.extends(SplitterPanel);
@@ -15,6 +15,7 @@ export default function AbsoluteStack(content, props = {}) {
15
15
  }
16
16
  PositionStack.call(this, content, props);
17
17
  this.$description.position = 'absolute';
18
+ this.aria = {};
18
19
  }
19
20
 
20
21
  BaseComponent.extends(AbsoluteStack, PositionStack);
@@ -15,6 +15,7 @@ export default function FixedStack(content, props = {}) {
15
15
  }
16
16
  PositionStack.call(this, content, props);
17
17
  this.$description.position = 'fixed';
18
+ this.aria = {};
18
19
  }
19
20
 
20
21
  BaseComponent.extends(FixedStack, PositionStack);
@@ -16,6 +16,7 @@ export default function HStack(content, props = {}) {
16
16
 
17
17
  Stack.call(this, content, props);
18
18
  this.$description.orientation = 'horizontal';
19
+ this.aria = {};
19
20
  }
20
21
 
21
22
  BaseComponent.extends(HStack, Stack);
@@ -34,6 +34,7 @@ export default function PositionStack(content, props = {}) {
34
34
  anchor: null,
35
35
  props,
36
36
  };
37
+ this.aria = {};
37
38
  }
38
39
 
39
40
  BaseComponent.extends(PositionStack);
@@ -15,6 +15,7 @@ export default function RelativeStack(content, props = {}) {
15
15
  }
16
16
  PositionStack.call(this, content, props);
17
17
  this.$description.position = 'relative';
18
+ this.aria = {};
18
19
  }
19
20
 
20
21
  BaseComponent.extends(RelativeStack, PositionStack);