semmet-angular 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/README.md +47 -7
  2. package/package.json +1 -1
  3. package/src/alert/files/__name@dasherize__/__name@dasherize__.css.template +43 -0
  4. package/src/alert/files/__name@dasherize__/__name@dasherize__.html.template +7 -0
  5. package/src/alert/files/__name@dasherize__/__name@dasherize__.ts.template +18 -0
  6. package/src/alert/index.d.ts +1 -0
  7. package/src/alert/index.js +6 -0
  8. package/src/alert/index.js.map +1 -0
  9. package/src/alert/index.ts +3 -0
  10. package/src/alert/schema.d.ts +1 -0
  11. package/src/alert/schema.js +3 -0
  12. package/src/alert/schema.js.map +1 -0
  13. package/src/alert/schema.json +29 -0
  14. package/src/alert/schema.ts +1 -0
  15. package/src/alert-dialog/files/__name@dasherize__/__name@dasherize__.css.template +82 -0
  16. package/src/alert-dialog/files/__name@dasherize__/__name@dasherize__.html.template +20 -0
  17. package/src/alert-dialog/files/__name@dasherize__/__name@dasherize__.ts.template +75 -0
  18. package/src/alert-dialog/index.d.ts +1 -0
  19. package/src/alert-dialog/index.js +6 -0
  20. package/src/alert-dialog/index.js.map +1 -0
  21. package/src/alert-dialog/index.ts +3 -0
  22. package/src/alert-dialog/schema.d.ts +1 -0
  23. package/src/alert-dialog/schema.js +3 -0
  24. package/src/alert-dialog/schema.js.map +1 -0
  25. package/src/alert-dialog/schema.json +29 -0
  26. package/src/alert-dialog/schema.ts +1 -0
  27. package/src/breadcrumb/files/__name@dasherize__/__name@dasherize__.css.template +52 -0
  28. package/src/breadcrumb/files/__name@dasherize__/__name@dasherize__.html.template +9 -0
  29. package/src/breadcrumb/files/__name@dasherize__/__name@dasherize__.ts.template +20 -0
  30. package/src/breadcrumb/index.d.ts +1 -0
  31. package/src/breadcrumb/index.js +6 -0
  32. package/src/breadcrumb/index.js.map +1 -0
  33. package/src/breadcrumb/index.ts +3 -0
  34. package/src/breadcrumb/schema.d.ts +1 -0
  35. package/src/breadcrumb/schema.js +3 -0
  36. package/src/breadcrumb/schema.js.map +1 -0
  37. package/src/breadcrumb/schema.json +29 -0
  38. package/src/breadcrumb/schema.ts +1 -0
  39. package/src/card/files/__name@dasherize__/__name@dasherize__.css.template +49 -0
  40. package/src/card/files/__name@dasherize__/__name@dasherize__.html.template +6 -0
  41. package/src/card/files/__name@dasherize__/__name@dasherize__.ts.template +13 -0
  42. package/src/card/index.d.ts +1 -0
  43. package/src/card/index.js +6 -0
  44. package/src/card/index.js.map +1 -0
  45. package/src/card/index.ts +3 -0
  46. package/src/card/schema.d.ts +1 -0
  47. package/src/card/schema.js +3 -0
  48. package/src/card/schema.js.map +1 -0
  49. package/src/card/schema.json +29 -0
  50. package/src/card/schema.ts +1 -0
  51. package/src/carousel/files/__name@dasherize__/__name@dasherize__.css.template +58 -0
  52. package/src/carousel/files/__name@dasherize__/__name@dasherize__.html.template +10 -0
  53. package/src/carousel/files/__name@dasherize__/__name@dasherize__.ts.template +35 -0
  54. package/src/carousel/index.d.ts +1 -0
  55. package/src/carousel/index.js +6 -0
  56. package/src/carousel/index.js.map +1 -0
  57. package/src/carousel/index.ts +3 -0
  58. package/src/carousel/schema.d.ts +1 -0
  59. package/src/carousel/schema.js +3 -0
  60. package/src/carousel/schema.js.map +1 -0
  61. package/src/carousel/schema.json +29 -0
  62. package/src/carousel/schema.ts +1 -0
  63. package/src/checkbox/files/__name@dasherize__/__name@dasherize__.css.template +62 -0
  64. package/src/checkbox/files/__name@dasherize__/__name@dasherize__.html.template +11 -0
  65. package/src/checkbox/files/__name@dasherize__/__name@dasherize__.ts.template +25 -0
  66. package/src/checkbox/index.d.ts +1 -0
  67. package/src/checkbox/index.js +6 -0
  68. package/src/checkbox/index.js.map +1 -0
  69. package/src/checkbox/index.ts +3 -0
  70. package/src/checkbox/schema.d.ts +1 -0
  71. package/src/checkbox/schema.js +3 -0
  72. package/src/checkbox/schema.js.map +1 -0
  73. package/src/checkbox/schema.json +29 -0
  74. package/src/checkbox/schema.ts +1 -0
  75. package/src/collection.json +115 -0
  76. package/src/combobox/files/__name@dasherize__/__name@dasherize__.css.template +75 -0
  77. package/src/combobox/files/__name@dasherize__/__name@dasherize__.html.template +33 -0
  78. package/src/combobox/files/__name@dasherize__/__name@dasherize__.ts.template +93 -0
  79. package/src/combobox/index.d.ts +1 -0
  80. package/src/combobox/index.js +6 -0
  81. package/src/combobox/index.js.map +1 -0
  82. package/src/combobox/index.ts +3 -0
  83. package/src/combobox/schema.d.ts +1 -0
  84. package/src/combobox/schema.js +3 -0
  85. package/src/combobox/schema.js.map +1 -0
  86. package/src/combobox/schema.json +29 -0
  87. package/src/combobox/schema.ts +1 -0
  88. package/src/landmarks/files/__name@dasherize__/__name@dasherize__.css.template +61 -0
  89. package/src/landmarks/files/__name@dasherize__/__name@dasherize__.html.template +17 -0
  90. package/src/landmarks/files/__name@dasherize__/__name@dasherize__.ts.template +9 -0
  91. package/src/landmarks/index.d.ts +1 -0
  92. package/src/landmarks/index.js +6 -0
  93. package/src/landmarks/index.js.map +1 -0
  94. package/src/landmarks/index.ts +3 -0
  95. package/src/landmarks/schema.d.ts +1 -0
  96. package/src/landmarks/schema.js +3 -0
  97. package/src/landmarks/schema.js.map +1 -0
  98. package/src/landmarks/schema.json +29 -0
  99. package/src/landmarks/schema.ts +1 -0
  100. package/src/listbox/files/__name@dasherize__/__name@dasherize__.css.template +52 -0
  101. package/src/listbox/files/__name@dasherize__/__name@dasherize__.html.template +20 -0
  102. package/src/listbox/files/__name@dasherize__/__name@dasherize__.ts.template +54 -0
  103. package/src/listbox/index.d.ts +1 -0
  104. package/src/listbox/index.js +6 -0
  105. package/src/listbox/index.js.map +1 -0
  106. package/src/listbox/index.ts +3 -0
  107. package/src/listbox/schema.d.ts +1 -0
  108. package/src/listbox/schema.js +3 -0
  109. package/src/listbox/schema.js.map +1 -0
  110. package/src/listbox/schema.json +29 -0
  111. package/src/listbox/schema.ts +1 -0
  112. package/src/menu-button/files/__name@dasherize__/__name@dasherize__.css.template +82 -0
  113. package/src/menu-button/files/__name@dasherize__/__name@dasherize__.html.template +34 -0
  114. package/src/menu-button/files/__name@dasherize__/__name@dasherize__.ts.template +104 -0
  115. package/src/menu-button/index.d.ts +1 -0
  116. package/src/menu-button/index.js +6 -0
  117. package/src/menu-button/index.js.map +1 -0
  118. package/src/menu-button/index.ts +3 -0
  119. package/src/menu-button/schema.d.ts +1 -0
  120. package/src/menu-button/schema.js +3 -0
  121. package/src/menu-button/schema.js.map +1 -0
  122. package/src/menu-button/schema.json +29 -0
  123. package/src/menu-button/schema.ts +1 -0
  124. package/src/meter/files/__name@dasherize__/__name@dasherize__.css.template +22 -0
  125. package/src/meter/files/__name@dasherize__/__name@dasherize__.html.template +5 -0
  126. package/src/meter/files/__name@dasherize__/__name@dasherize__.ts.template +14 -0
  127. package/src/meter/index.d.ts +1 -0
  128. package/src/meter/index.js +6 -0
  129. package/src/meter/index.js.map +1 -0
  130. package/src/meter/index.ts +3 -0
  131. package/src/meter/schema.d.ts +1 -0
  132. package/src/meter/schema.js +3 -0
  133. package/src/meter/schema.js.map +1 -0
  134. package/src/meter/schema.json +29 -0
  135. package/src/meter/schema.ts +1 -0
  136. package/src/navigation-menu/files/__name@dasherize__/__name@dasherize__.css.template +88 -0
  137. package/src/navigation-menu/files/__name@dasherize__/__name@dasherize__.html.template +22 -0
  138. package/src/navigation-menu/files/__name@dasherize__/__name@dasherize__.ts.template +18 -0
  139. package/src/navigation-menu/index.d.ts +1 -0
  140. package/src/navigation-menu/index.js +6 -0
  141. package/src/navigation-menu/index.js.map +1 -0
  142. package/src/navigation-menu/index.ts +3 -0
  143. package/src/navigation-menu/schema.d.ts +1 -0
  144. package/src/navigation-menu/schema.js +3 -0
  145. package/src/navigation-menu/schema.js.map +1 -0
  146. package/src/navigation-menu/schema.json +29 -0
  147. package/src/navigation-menu/schema.ts +1 -0
  148. package/src/pagination/files/__name@dasherize__/__name@dasherize__.css.template +63 -0
  149. package/src/pagination/files/__name@dasherize__/__name@dasherize__.html.template +26 -0
  150. package/src/pagination/files/__name@dasherize__/__name@dasherize__.ts.template +31 -0
  151. package/src/pagination/index.d.ts +1 -0
  152. package/src/pagination/index.js +6 -0
  153. package/src/pagination/index.js.map +1 -0
  154. package/src/pagination/index.ts +3 -0
  155. package/src/pagination/schema.d.ts +1 -0
  156. package/src/pagination/schema.js +3 -0
  157. package/src/pagination/schema.js.map +1 -0
  158. package/src/pagination/schema.json +29 -0
  159. package/src/pagination/schema.ts +1 -0
  160. package/src/progress-bar/files/__name@dasherize__/__name@dasherize__.css.template +53 -0
  161. package/src/progress-bar/files/__name@dasherize__/__name@dasherize__.html.template +6 -0
  162. package/src/progress-bar/files/__name@dasherize__/__name@dasherize__.ts.template +19 -0
  163. package/src/progress-bar/index.d.ts +1 -0
  164. package/src/progress-bar/index.js +6 -0
  165. package/src/progress-bar/index.js.map +1 -0
  166. package/src/progress-bar/index.ts +3 -0
  167. package/src/progress-bar/schema.d.ts +1 -0
  168. package/src/progress-bar/schema.js +3 -0
  169. package/src/progress-bar/schema.js.map +1 -0
  170. package/src/progress-bar/schema.json +29 -0
  171. package/src/progress-bar/schema.ts +1 -0
  172. package/src/radio-group/files/__name@dasherize__/__name@dasherize__.css.template +66 -0
  173. package/src/radio-group/files/__name@dasherize__/__name@dasherize__.html.template +16 -0
  174. package/src/radio-group/files/__name@dasherize__/__name@dasherize__.ts.template +62 -0
  175. package/src/radio-group/index.d.ts +1 -0
  176. package/src/radio-group/index.js +6 -0
  177. package/src/radio-group/index.js.map +1 -0
  178. package/src/radio-group/index.ts +3 -0
  179. package/src/radio-group/schema.d.ts +1 -0
  180. package/src/radio-group/schema.js +3 -0
  181. package/src/radio-group/schema.js.map +1 -0
  182. package/src/radio-group/schema.json +29 -0
  183. package/src/radio-group/schema.ts +1 -0
  184. package/src/skip-link/files/__name@dasherize__/__name@dasherize__.css.template +30 -0
  185. package/src/skip-link/files/__name@dasherize__/__name@dasherize__.html.template +3 -0
  186. package/src/skip-link/files/__name@dasherize__/__name@dasherize__.ts.template +9 -0
  187. package/src/skip-link/index.d.ts +1 -0
  188. package/src/skip-link/index.js +6 -0
  189. package/src/skip-link/index.js.map +1 -0
  190. package/src/skip-link/index.ts +3 -0
  191. package/src/skip-link/schema.d.ts +1 -0
  192. package/src/skip-link/schema.js +3 -0
  193. package/src/skip-link/schema.js.map +1 -0
  194. package/src/skip-link/schema.json +29 -0
  195. package/src/skip-link/schema.ts +1 -0
  196. package/src/slider/files/__name@dasherize__/__name@dasherize__.css.template +54 -0
  197. package/src/slider/files/__name@dasherize__/__name@dasherize__.html.template +16 -0
  198. package/src/slider/files/__name@dasherize__/__name@dasherize__.ts.template +79 -0
  199. package/src/slider/index.d.ts +1 -0
  200. package/src/slider/index.js +6 -0
  201. package/src/slider/index.js.map +1 -0
  202. package/src/slider/index.ts +3 -0
  203. package/src/slider/schema.d.ts +1 -0
  204. package/src/slider/schema.js +3 -0
  205. package/src/slider/schema.js.map +1 -0
  206. package/src/slider/schema.json +29 -0
  207. package/src/slider/schema.ts +1 -0
  208. package/src/spinbutton/files/__name@dasherize__/__name@dasherize__.css.template +64 -0
  209. package/src/spinbutton/files/__name@dasherize__/__name@dasherize__.html.template +19 -0
  210. package/src/spinbutton/files/__name@dasherize__/__name@dasherize__.ts.template +59 -0
  211. package/src/spinbutton/index.d.ts +1 -0
  212. package/src/spinbutton/index.js +6 -0
  213. package/src/spinbutton/index.js.map +1 -0
  214. package/src/spinbutton/index.ts +3 -0
  215. package/src/spinbutton/schema.d.ts +1 -0
  216. package/src/spinbutton/schema.js +3 -0
  217. package/src/spinbutton/schema.js.map +1 -0
  218. package/src/spinbutton/schema.json +29 -0
  219. package/src/spinbutton/schema.ts +1 -0
  220. package/src/switch/files/__name@dasherize__/__name@dasherize__.css.template +68 -0
  221. package/src/switch/files/__name@dasherize__/__name@dasherize__.html.template +4 -0
  222. package/src/switch/files/__name@dasherize__/__name@dasherize__.ts.template +18 -0
  223. package/src/switch/index.d.ts +1 -0
  224. package/src/switch/index.js +6 -0
  225. package/src/switch/index.js.map +1 -0
  226. package/src/switch/index.ts +3 -0
  227. package/src/switch/schema.d.ts +1 -0
  228. package/src/switch/schema.js +3 -0
  229. package/src/switch/schema.js.map +1 -0
  230. package/src/switch/schema.json +29 -0
  231. package/src/switch/schema.ts +1 -0
  232. package/src/table/files/__name@dasherize__/__name@dasherize__.css.template +40 -0
  233. package/src/table/files/__name@dasherize__/__name@dasherize__.html.template +18 -0
  234. package/src/table/files/__name@dasherize__/__name@dasherize__.ts.template +19 -0
  235. package/src/table/index.d.ts +1 -0
  236. package/src/table/index.js +6 -0
  237. package/src/table/index.js.map +1 -0
  238. package/src/table/index.ts +3 -0
  239. package/src/table/schema.d.ts +1 -0
  240. package/src/table/schema.js +3 -0
  241. package/src/table/schema.js.map +1 -0
  242. package/src/table/schema.json +29 -0
  243. package/src/table/schema.ts +1 -0
  244. package/src/toast/files/__name@dasherize__/__name@dasherize__.css.template +56 -0
  245. package/src/toast/files/__name@dasherize__/__name@dasherize__.html.template +9 -0
  246. package/src/toast/files/__name@dasherize__/__name@dasherize__.ts.template +33 -0
  247. package/src/toast/index.d.ts +1 -0
  248. package/src/toast/index.js +6 -0
  249. package/src/toast/index.js.map +1 -0
  250. package/src/toast/index.ts +3 -0
  251. package/src/toast/schema.d.ts +1 -0
  252. package/src/toast/schema.js +3 -0
  253. package/src/toast/schema.js.map +1 -0
  254. package/src/toast/schema.json +29 -0
  255. package/src/toast/schema.ts +1 -0
  256. package/src/toolbar/files/__name@dasherize__/__name@dasherize__.css.template +48 -0
  257. package/src/toolbar/files/__name@dasherize__/__name@dasherize__.html.template +15 -0
  258. package/src/toolbar/files/__name@dasherize__/__name@dasherize__.ts.template +71 -0
  259. package/src/toolbar/index.d.ts +1 -0
  260. package/src/toolbar/index.js +6 -0
  261. package/src/toolbar/index.js.map +1 -0
  262. package/src/toolbar/index.ts +3 -0
  263. package/src/toolbar/schema.d.ts +1 -0
  264. package/src/toolbar/schema.js +3 -0
  265. package/src/toolbar/schema.js.map +1 -0
  266. package/src/toolbar/schema.json +29 -0
  267. package/src/toolbar/schema.ts +1 -0
  268. package/src/tree-view/files/__name@dasherize__/__name@dasherize__.css.template +57 -0
  269. package/src/tree-view/files/__name@dasherize__/__name@dasherize__.html.template +30 -0
  270. package/src/tree-view/files/__name@dasherize__/__name@dasherize__.ts.template +140 -0
  271. package/src/tree-view/index.d.ts +1 -0
  272. package/src/tree-view/index.js +6 -0
  273. package/src/tree-view/index.js.map +1 -0
  274. package/src/tree-view/index.ts +3 -0
  275. package/src/tree-view/schema.d.ts +1 -0
  276. package/src/tree-view/schema.js +3 -0
  277. package/src/tree-view/schema.js.map +1 -0
  278. package/src/tree-view/schema.json +29 -0
  279. package/src/tree-view/schema.ts +1 -0
@@ -0,0 +1,75 @@
1
+ :host {
2
+ --semmet-color-primary: #0d7a72;
3
+ --semmet-color-surface: #ffffff;
4
+ --semmet-color-outline: #d7dedd;
5
+ --semmet-color-on-surface: #1b201f;
6
+ --semmet-color-on-surface-variant: #576260;
7
+ --semmet-radius-sm: 8px;
8
+ --semmet-radius-md: 12px;
9
+ --semmet-elevation-3: 0 8px 24px rgba(20, 24, 23, 0.18), 0 2px 8px rgba(20, 24, 23, 0.1);
10
+ --semmet-motion: 160ms cubic-bezier(0.2, 0, 0, 1);
11
+
12
+ position: relative;
13
+ display: inline-block;
14
+ font-family: Roboto, system-ui, -apple-system, 'Segoe UI', sans-serif;
15
+ font-size: 0.9375rem;
16
+ }
17
+
18
+ label {
19
+ display: block;
20
+ margin-bottom: 0.375rem;
21
+ font-weight: 500;
22
+ color: var(--semmet-color-on-surface);
23
+ }
24
+
25
+ input {
26
+ width: 100%;
27
+ min-width: 14rem;
28
+ font: inherit;
29
+ color: var(--semmet-color-on-surface);
30
+ background: var(--semmet-color-surface);
31
+ border: 1px solid var(--semmet-color-outline);
32
+ border-radius: var(--semmet-radius-sm);
33
+ padding: 0.5rem 0.75rem;
34
+ box-sizing: border-box;
35
+ transition: border-color var(--semmet-motion);
36
+ }
37
+
38
+ input:focus-visible {
39
+ outline: 2px solid var(--semmet-color-primary);
40
+ outline-offset: 1px;
41
+ border-color: var(--semmet-color-primary);
42
+ }
43
+
44
+ ul {
45
+ position: absolute;
46
+ z-index: 1;
47
+ top: 100%;
48
+ left: 0;
49
+ right: 0;
50
+ margin: 0.25rem 0 0;
51
+ padding: 0.375rem;
52
+ list-style: none;
53
+ background: var(--semmet-color-surface);
54
+ border-radius: var(--semmet-radius-md);
55
+ box-shadow: var(--semmet-elevation-3);
56
+ max-height: 12rem;
57
+ overflow-y: auto;
58
+ }
59
+
60
+ [role='option'] {
61
+ padding: 0.5rem 0.75rem;
62
+ border-radius: 6px;
63
+ color: var(--semmet-color-on-surface);
64
+ cursor: pointer;
65
+ transition: background-color var(--semmet-motion);
66
+ }
67
+
68
+ [role='option'][aria-selected='true'] {
69
+ background: color-mix(in srgb, var(--semmet-color-primary) 12%, transparent);
70
+ color: var(--semmet-color-primary);
71
+ }
72
+
73
+ [role='option']:hover {
74
+ background: color-mix(in srgb, var(--semmet-color-on-surface) 6%, transparent);
75
+ }
@@ -0,0 +1,33 @@
1
+ <!-- Semmet Angular: Combobox — https://www.w3.org/WAI/ARIA/apg/patterns/combobox/ -->
2
+ <label [id]="instanceId + '-label'" [for]="instanceId + '-input'">Choose a fruit</label>
3
+ <input
4
+ type="text"
5
+ [id]="instanceId + '-input'"
6
+ role="combobox"
7
+ [attr.aria-expanded]="isOpen()"
8
+ [attr.aria-controls]="instanceId + '-listbox'"
9
+ aria-autocomplete="list"
10
+ [attr.aria-activedescendant]="activeDescendantId()"
11
+ [attr.aria-labelledby]="instanceId + '-label'"
12
+ [value]="query()"
13
+ (input)="onInput($event)"
14
+ (keydown)="handleInputKeydown($event)"
15
+ (focus)="openList()"
16
+ />
17
+ <ul
18
+ role="listbox"
19
+ [id]="instanceId + '-listbox'"
20
+ [attr.aria-labelledby]="instanceId + '-label'"
21
+ [hidden]="!isOpen() || filteredItems().length === 0"
22
+ >
23
+ @for (item of filteredItems(); track item.id; let i = $index) {
24
+ <li
25
+ role="option"
26
+ [id]="instanceId + '-option-' + item.id"
27
+ [attr.aria-selected]="i === activeIndex()"
28
+ (click)="select(item)"
29
+ >
30
+ {{ item.label }}
31
+ </li>
32
+ }
33
+ </ul>
@@ -0,0 +1,93 @@
1
+ import { Component, computed, signal } from '@angular/core';
2
+
3
+ interface <%= classify(name) %>Item {
4
+ id: number;
5
+ label: string;
6
+ }
7
+
8
+ let nextId = 0;
9
+
10
+ @Component({
11
+ selector: '<%= selector %>',
12
+ imports: [],
13
+ templateUrl: './<%= dasherize(name) %>.html',
14
+ styleUrl: './<%= dasherize(name) %>.css',
15
+ })
16
+ export class <%= classify(name) %> {
17
+ protected readonly instanceId = `<%= dasherize(name) %>-${nextId++}`;
18
+ protected readonly items: <%= classify(name) %>Item[] = [
19
+ { id: 1, label: 'Apple' },
20
+ { id: 2, label: 'Banana' },
21
+ { id: 3, label: 'Cherry' },
22
+ ];
23
+
24
+ protected readonly query = signal('');
25
+ protected readonly isOpen = signal(false);
26
+ protected readonly activeIndex = signal(-1);
27
+
28
+ protected readonly filteredItems = computed(() =>
29
+ this.items.filter((item) => item.label.toLowerCase().includes(this.query().toLowerCase()))
30
+ );
31
+
32
+ protected readonly activeDescendantId = computed(() => {
33
+ const active = this.filteredItems()[this.activeIndex()];
34
+ return active ? `${this.instanceId}-option-${active.id}` : null;
35
+ });
36
+
37
+ protected openList(): void {
38
+ this.isOpen.set(true);
39
+ }
40
+
41
+ protected onInput(event: Event): void {
42
+ const value = (event.target as HTMLInputElement).value;
43
+ this.query.set(value);
44
+ this.isOpen.set(true);
45
+ this.activeIndex.set(-1);
46
+ }
47
+
48
+ protected select(item: <%= classify(name) %>Item): void {
49
+ this.query.set(item.label);
50
+ this.isOpen.set(false);
51
+ this.activeIndex.set(-1);
52
+ }
53
+
54
+ protected handleInputKeydown(event: KeyboardEvent): void {
55
+ const options = this.filteredItems();
56
+
57
+ switch (event.key) {
58
+ case 'ArrowDown':
59
+ event.preventDefault();
60
+ this.isOpen.set(true);
61
+ this.activeIndex.update((index) => Math.min(index + 1, options.length - 1));
62
+ break;
63
+ case 'ArrowUp':
64
+ event.preventDefault();
65
+ this.activeIndex.update((index) => Math.max(index - 1, 0));
66
+ break;
67
+ case 'Home':
68
+ if (this.isOpen()) {
69
+ event.preventDefault();
70
+ this.activeIndex.set(0);
71
+ }
72
+ break;
73
+ case 'End':
74
+ if (this.isOpen()) {
75
+ event.preventDefault();
76
+ this.activeIndex.set(options.length - 1);
77
+ }
78
+ break;
79
+ case 'Enter': {
80
+ const active = options[this.activeIndex()];
81
+ if (active) {
82
+ event.preventDefault();
83
+ this.select(active);
84
+ }
85
+ break;
86
+ }
87
+ case 'Escape':
88
+ this.isOpen.set(false);
89
+ this.activeIndex.set(-1);
90
+ break;
91
+ }
92
+ }
93
+ }
@@ -0,0 +1 @@
1
+ export declare const combobox: (options: import("./schema").Schema) => import("@angular-devkit/schematics").Rule;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.combobox = void 0;
4
+ const generate_component_1 = require("../utils/generate-component");
5
+ exports.combobox = (0, generate_component_1.createAriaComponentSchematic)();
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,QAAQ,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { createAriaComponentSchematic } from '../utils/generate-component';
2
+
3
+ export const combobox = createAriaComponentSchematic();
@@ -0,0 +1 @@
1
+ export { ComponentSchematicOptions as Schema } from '../utils/schema-types';
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["schema.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "SemmetAngularCombobox",
4
+ "title": "Semmet Angular Combobox Options Schema",
5
+ "type": "object",
6
+ "description": "Generates a standalone Angular Combobox component (list autocomplete, active-descendant model) following the W3C ARIA Authoring Practices Guide.",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "The name for the new component. Used to derive the class name, selector, and file names.",
12
+ "$default": { "$source": "argv", "index": 0 },
13
+ "x-prompt": "What name would you like to use for the combobox component?"
14
+ },
15
+ "path": {
16
+ "type": "string",
17
+ "format": "path",
18
+ "$default": { "$source": "workingDirectory" },
19
+ "description": "The path where the component files should be created, relative to the workspace root. Defaults to the project's source root.",
20
+ "visible": false
21
+ },
22
+ "project": {
23
+ "type": "string",
24
+ "description": "The name of the project to add the component to.",
25
+ "$default": { "$source": "projectName" }
26
+ }
27
+ },
28
+ "required": ["name", "project"]
29
+ }
@@ -0,0 +1 @@
1
+ export { ComponentSchematicOptions as Schema } from '../utils/schema-types';
@@ -0,0 +1,61 @@
1
+ :host {
2
+ --semmet-color-outline: #d7dedd;
3
+ --semmet-color-on-surface: #1b201f;
4
+ --semmet-color-on-surface-variant: #576260;
5
+
6
+ display: grid;
7
+ grid-template-columns: 1fr;
8
+ gap: 1.5rem;
9
+ font-family: Roboto, system-ui, -apple-system, 'Segoe UI', sans-serif;
10
+ color: var(--semmet-color-on-surface);
11
+ }
12
+
13
+ header,
14
+ nav,
15
+ footer {
16
+ padding: 1rem 0;
17
+ }
18
+
19
+ header {
20
+ border-bottom: 1px solid var(--semmet-color-outline);
21
+ }
22
+
23
+ footer {
24
+ border-top: 1px solid var(--semmet-color-outline);
25
+ color: var(--semmet-color-on-surface-variant);
26
+ }
27
+
28
+ main {
29
+ min-height: 12rem;
30
+ }
31
+
32
+ @media (min-width: 48rem) {
33
+ :host {
34
+ grid-template-columns: 1fr 16rem;
35
+ grid-template-areas:
36
+ 'header header'
37
+ 'nav nav'
38
+ 'main aside'
39
+ 'footer footer';
40
+ }
41
+
42
+ header {
43
+ grid-area: header;
44
+ }
45
+
46
+ nav {
47
+ grid-area: nav;
48
+ }
49
+
50
+ main {
51
+ grid-area: main;
52
+ }
53
+
54
+ aside {
55
+ grid-area: aside;
56
+ }
57
+
58
+ footer {
59
+ grid-area: footer;
60
+ }
61
+ }
@@ -0,0 +1,17 @@
1
+ <!-- Semmet Angular: Landmarks (Page Skeleton) — https://www.w3.org/WAI/ARIA/apg/practices/landmark-regions/ -->
2
+ <!-- Project content into a region with the matching attribute, e.g. <div header>...</div>. Unmatched content goes to <main>. -->
3
+ <header>
4
+ <ng-content select="[header]"></ng-content>
5
+ </header>
6
+ <nav aria-label="Main">
7
+ <ng-content select="[nav]"></ng-content>
8
+ </nav>
9
+ <main>
10
+ <ng-content></ng-content>
11
+ </main>
12
+ <aside aria-label="Related links">
13
+ <ng-content select="[aside]"></ng-content>
14
+ </aside>
15
+ <footer>
16
+ <ng-content select="[footer]"></ng-content>
17
+ </footer>
@@ -0,0 +1,9 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: '<%= selector %>',
5
+ imports: [],
6
+ templateUrl: './<%= dasherize(name) %>.html',
7
+ styleUrl: './<%= dasherize(name) %>.css',
8
+ })
9
+ export class <%= classify(name) %> {}
@@ -0,0 +1 @@
1
+ export declare const landmarks: (options: import("./schema").Schema) => import("@angular-devkit/schematics").Rule;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.landmarks = void 0;
4
+ const generate_component_1 = require("../utils/generate-component");
5
+ exports.landmarks = (0, generate_component_1.createAriaComponentSchematic)();
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,SAAS,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { createAriaComponentSchematic } from '../utils/generate-component';
2
+
3
+ export const landmarks = createAriaComponentSchematic();
@@ -0,0 +1 @@
1
+ export { ComponentSchematicOptions as Schema } from '../utils/schema-types';
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["schema.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "SemmetAngularLandmarks",
4
+ "title": "Semmet Angular Landmarks Options Schema",
5
+ "type": "object",
6
+ "description": "Generates a standalone Angular page-skeleton layout component (header/nav/main/aside/footer landmarks with content projection), following W3C ARIA landmark region guidance.",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "The name for the new component. Used to derive the class name, selector, and file names.",
12
+ "$default": { "$source": "argv", "index": 0 },
13
+ "x-prompt": "What name would you like to use for the layout component?"
14
+ },
15
+ "path": {
16
+ "type": "string",
17
+ "format": "path",
18
+ "$default": { "$source": "workingDirectory" },
19
+ "description": "The path where the component files should be created, relative to the workspace root. Defaults to the project's source root.",
20
+ "visible": false
21
+ },
22
+ "project": {
23
+ "type": "string",
24
+ "description": "The name of the project to add the component to.",
25
+ "$default": { "$source": "projectName" }
26
+ }
27
+ },
28
+ "required": ["name", "project"]
29
+ }
@@ -0,0 +1 @@
1
+ export { ComponentSchematicOptions as Schema } from '../utils/schema-types';
@@ -0,0 +1,52 @@
1
+ :host {
2
+ --semmet-color-primary: #0d7a72;
3
+ --semmet-color-surface: #ffffff;
4
+ --semmet-color-outline: #d7dedd;
5
+ --semmet-color-on-surface: #1b201f;
6
+ --semmet-radius-sm: 8px;
7
+ --semmet-motion: 160ms cubic-bezier(0.2, 0, 0, 1);
8
+
9
+ display: block;
10
+ font-family: Roboto, system-ui, -apple-system, 'Segoe UI', sans-serif;
11
+ font-size: 0.9375rem;
12
+ }
13
+
14
+ span {
15
+ display: block;
16
+ margin-bottom: 0.5rem;
17
+ font-weight: 500;
18
+ color: var(--semmet-color-on-surface);
19
+ }
20
+
21
+ ul {
22
+ margin: 0;
23
+ padding: 0.375rem;
24
+ list-style: none;
25
+ border: 1px solid var(--semmet-color-outline);
26
+ border-radius: var(--semmet-radius-sm);
27
+ background: var(--semmet-color-surface);
28
+ max-width: 16rem;
29
+ }
30
+
31
+ ul:focus-visible {
32
+ outline: 2px solid var(--semmet-color-primary);
33
+ outline-offset: 1px;
34
+ }
35
+
36
+ [role='option'] {
37
+ padding: 0.5rem 0.75rem;
38
+ border-radius: 6px;
39
+ color: var(--semmet-color-on-surface);
40
+ cursor: pointer;
41
+ transition: background-color var(--semmet-motion);
42
+ }
43
+
44
+ [role='option'][aria-selected='true'] {
45
+ background: color-mix(in srgb, var(--semmet-color-primary) 12%, transparent);
46
+ color: var(--semmet-color-primary);
47
+ font-weight: 500;
48
+ }
49
+
50
+ [role='option']:hover {
51
+ background: color-mix(in srgb, var(--semmet-color-on-surface) 6%, transparent);
52
+ }
@@ -0,0 +1,20 @@
1
+ <!-- Semmet Angular: Listbox — https://www.w3.org/WAI/ARIA/apg/patterns/listbox/ -->
2
+ <span [id]="instanceId + '-label'">Choose an option</span>
3
+ <ul
4
+ role="listbox"
5
+ [attr.aria-labelledby]="instanceId + '-label'"
6
+ [attr.aria-activedescendant]="activeDescendantId()"
7
+ tabindex="0"
8
+ (keydown)="navigateList($event)"
9
+ >
10
+ @for (option of options; track option.id; let i = $index) {
11
+ <li
12
+ role="option"
13
+ [id]="instanceId + '-option-' + option.id"
14
+ [attr.aria-selected]="i === activeIndex()"
15
+ (click)="select(i)"
16
+ >
17
+ {{ option.label }}
18
+ </li>
19
+ }
20
+ </ul>
@@ -0,0 +1,54 @@
1
+ import { Component, computed, signal } from '@angular/core';
2
+
3
+ interface <%= classify(name) %>Option {
4
+ id: number;
5
+ label: string;
6
+ }
7
+
8
+ let nextId = 0;
9
+
10
+ @Component({
11
+ selector: '<%= selector %>',
12
+ imports: [],
13
+ templateUrl: './<%= dasherize(name) %>.html',
14
+ styleUrl: './<%= dasherize(name) %>.css',
15
+ })
16
+ export class <%= classify(name) %> {
17
+ protected readonly instanceId = `<%= dasherize(name) %>-${nextId++}`;
18
+ protected readonly options: <%= classify(name) %>Option[] = [
19
+ { id: 1, label: 'First option' },
20
+ { id: 2, label: 'Second option' },
21
+ ];
22
+
23
+ protected readonly activeIndex = signal(0);
24
+
25
+ protected readonly activeDescendantId = computed(
26
+ () => `${this.instanceId}-option-${this.options[this.activeIndex()].id}`
27
+ );
28
+
29
+ protected select(index: number): void {
30
+ this.activeIndex.set(index);
31
+ }
32
+
33
+ // Up/Down move the active option; Home/End jump to first/last (APG listbox, active-descendant model).
34
+ protected navigateList(event: KeyboardEvent): void {
35
+ switch (event.key) {
36
+ case 'ArrowDown':
37
+ event.preventDefault();
38
+ this.activeIndex.update((index) => Math.min(index + 1, this.options.length - 1));
39
+ break;
40
+ case 'ArrowUp':
41
+ event.preventDefault();
42
+ this.activeIndex.update((index) => Math.max(index - 1, 0));
43
+ break;
44
+ case 'Home':
45
+ event.preventDefault();
46
+ this.activeIndex.set(0);
47
+ break;
48
+ case 'End':
49
+ event.preventDefault();
50
+ this.activeIndex.set(this.options.length - 1);
51
+ break;
52
+ }
53
+ }
54
+ }
@@ -0,0 +1 @@
1
+ export declare const listbox: (options: import("./schema").Schema) => import("@angular-devkit/schematics").Rule;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listbox = void 0;
4
+ const generate_component_1 = require("../utils/generate-component");
5
+ exports.listbox = (0, generate_component_1.createAriaComponentSchematic)();
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,oEAA2E;AAE9D,QAAA,OAAO,GAAG,IAAA,iDAA4B,GAAE,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { createAriaComponentSchematic } from '../utils/generate-component';
2
+
3
+ export const listbox = createAriaComponentSchematic();
@@ -0,0 +1 @@
1
+ export { ComponentSchematicOptions as Schema } from '../utils/schema-types';
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["schema.ts"],"names":[],"mappings":""}
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema",
3
+ "$id": "SemmetAngularListbox",
4
+ "title": "Semmet Angular Listbox Options Schema",
5
+ "type": "object",
6
+ "description": "Generates a standalone Angular Listbox component (active-descendant model) following the W3C ARIA Authoring Practices Guide.",
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "name": {
10
+ "type": "string",
11
+ "description": "The name for the new component. Used to derive the class name, selector, and file names.",
12
+ "$default": { "$source": "argv", "index": 0 },
13
+ "x-prompt": "What name would you like to use for the listbox component?"
14
+ },
15
+ "path": {
16
+ "type": "string",
17
+ "format": "path",
18
+ "$default": { "$source": "workingDirectory" },
19
+ "description": "The path where the component files should be created, relative to the workspace root. Defaults to the project's source root.",
20
+ "visible": false
21
+ },
22
+ "project": {
23
+ "type": "string",
24
+ "description": "The name of the project to add the component to.",
25
+ "$default": { "$source": "projectName" }
26
+ }
27
+ },
28
+ "required": ["name", "project"]
29
+ }
@@ -0,0 +1 @@
1
+ export { ComponentSchematicOptions as Schema } from '../utils/schema-types';