semmet-angular 0.42.0 → 0.44.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 (218) hide show
  1. package/README.en.md +2 -315
  2. package/README.md +172 -264
  3. package/package.json +2 -2
  4. package/src/accordion/files/__name@dasherize__/__name@dasherize__.css.template +4 -41
  5. package/src/accordion/schema.json +19 -4
  6. package/src/alert/files/__name@dasherize__/__name@dasherize__.css.template +1 -25
  7. package/src/alert/files/__name@dasherize__/__name@dasherize__.html.template +3 -3
  8. package/src/alert/files/__name@dasherize__/__name@dasherize__.ts.template +4 -1
  9. package/src/alert/schema.json +19 -4
  10. package/src/alert-dialog/files/__name@dasherize__/__name@dasherize__.css.template +3 -56
  11. package/src/alert-dialog/files/__name@dasherize__/__name@dasherize__.html.template +6 -6
  12. package/src/alert-dialog/files/__name@dasherize__/__name@dasherize__.ts.template +7 -1
  13. package/src/alert-dialog/schema.json +19 -4
  14. package/src/avatar/files/__name@dasherize__/__name@dasherize__.css.template +17 -0
  15. package/src/avatar/files/__name@dasherize__/__name@dasherize__.html.template +28 -0
  16. package/src/avatar/files/__name@dasherize__/__name@dasherize__.spec.ts.template +27 -0
  17. package/src/avatar/files/__name@dasherize__/__name@dasherize__.ts.template +35 -0
  18. package/src/avatar/index.d.ts +1 -0
  19. package/src/avatar/index.js +6 -0
  20. package/src/avatar/index.js.map +1 -0
  21. package/src/avatar/index.ts +3 -0
  22. package/src/avatar/schema.d.ts +1 -0
  23. package/src/avatar/schema.js +3 -0
  24. package/src/avatar/schema.js.map +1 -0
  25. package/src/avatar/schema.json +44 -0
  26. package/src/avatar/schema.ts +1 -0
  27. package/src/badge/files/__name@dasherize__/__name@dasherize__.css.template +0 -77
  28. package/src/badge/files/__name@dasherize__/__name@dasherize__.ts.template +2 -5
  29. package/src/badge/schema.json +19 -4
  30. package/src/block/files/__name@dasherize__/__name@dasherize__.css.template +10 -81
  31. package/src/block/files/__name@dasherize__/__name@dasherize__.html.template +33 -25
  32. package/src/block/files/__name@dasherize__/__name@dasherize__.ts.template +41 -10
  33. package/src/block/schema.json +19 -4
  34. package/src/breadcrumb/files/__name@dasherize__/__name@dasherize__.css.template +2 -23
  35. package/src/breadcrumb/files/__name@dasherize__/__name@dasherize__.html.template +4 -4
  36. package/src/breadcrumb/files/__name@dasherize__/__name@dasherize__.ts.template +9 -5
  37. package/src/breadcrumb/schema.json +19 -4
  38. package/src/button/files/__name@dasherize__/__name@dasherize__.css.template +2 -79
  39. package/src/button/files/__name@dasherize__/__name@dasherize__.ts.template +2 -5
  40. package/src/button/schema.json +19 -4
  41. package/src/button-group/files/__name@dasherize__/__name@dasherize__.css.template +2 -70
  42. package/src/button-group/files/__name@dasherize__/__name@dasherize__.ts.template +1 -2
  43. package/src/button-group/schema.json +19 -4
  44. package/src/card/files/__name@dasherize__/__name@dasherize__.css.template +0 -67
  45. package/src/card/files/__name@dasherize__/__name@dasherize__.html.template +10 -55
  46. package/src/card/files/__name@dasherize__/__name@dasherize__.ts.template +2 -45
  47. package/src/card/schema.json +19 -4
  48. package/src/carousel/files/__name@dasherize__/__name@dasherize__.css.template +2 -32
  49. package/src/carousel/files/__name@dasherize__/__name@dasherize__.html.template +4 -4
  50. package/src/carousel/files/__name@dasherize__/__name@dasherize__.ts.template +4 -0
  51. package/src/carousel/schema.json +19 -4
  52. package/src/checkbox/files/__name@dasherize__/__name@dasherize__.css.template +5 -21
  53. package/src/checkbox/schema.json +19 -4
  54. package/src/close-button/files/__name@dasherize__/__name@dasherize__.css.template +9 -47
  55. package/src/close-button/files/__name@dasherize__/__name@dasherize__.ts.template +2 -5
  56. package/src/close-button/schema.json +19 -4
  57. package/src/collection.json +21 -1
  58. package/src/combobox/files/__name@dasherize__/__name@dasherize__.css.template +4 -49
  59. package/src/combobox/files/__name@dasherize__/__name@dasherize__.html.template +2 -2
  60. package/src/combobox/files/__name@dasherize__/__name@dasherize__.ts.template +11 -8
  61. package/src/combobox/schema.json +19 -4
  62. package/src/dialog/files/__name@dasherize__/__name@dasherize__.css.template +3 -45
  63. package/src/dialog/files/__name@dasherize__/__name@dasherize__.html.template +5 -5
  64. package/src/dialog/files/__name@dasherize__/__name@dasherize__.ts.template +6 -1
  65. package/src/dialog/schema.json +19 -4
  66. package/src/disclosure/files/__name@dasherize__/__name@dasherize__.css.template +4 -36
  67. package/src/disclosure/schema.json +19 -4
  68. package/src/e2e/index.d.ts +2 -0
  69. package/src/e2e/index.js +90 -0
  70. package/src/e2e/index.js.map +1 -0
  71. package/src/e2e/index.ts +106 -0
  72. package/src/e2e/schema.d.ts +2 -0
  73. package/src/e2e/schema.js +3 -0
  74. package/src/e2e/schema.js.map +1 -0
  75. package/src/e2e/schema.json +9 -0
  76. package/src/e2e/schema.ts +1 -0
  77. package/src/form/files/__name@dasherize__/__name@dasherize__.css.template +1 -77
  78. package/src/form/files/__name@dasherize__/__name@dasherize__.html.template +7 -7
  79. package/src/form/files/__name@dasherize__/__name@dasherize__.ts.template +20 -7
  80. package/src/form/schema.json +19 -4
  81. package/src/input/files/__name@dasherize__/__name@dasherize__.css.template +2 -58
  82. package/src/input/schema.json +19 -4
  83. package/src/input-group/files/__name@dasherize__/__name@dasherize__.css.template +2 -68
  84. package/src/input-group/files/__name@dasherize__/__name@dasherize__.html.template +13 -5
  85. package/src/input-group/files/__name@dasherize__/__name@dasherize__.ts.template +21 -6
  86. package/src/input-group/schema.json +19 -4
  87. package/src/landmarks/files/__name@dasherize__/__name@dasherize__.css.template +0 -24
  88. package/src/landmarks/files/__name@dasherize__/__name@dasherize__.html.template +2 -2
  89. package/src/landmarks/files/__name@dasherize__/__name@dasherize__.ts.template +5 -2
  90. package/src/landmarks/schema.json +19 -4
  91. package/src/list-group/files/__name@dasherize__/__name@dasherize__.css.template +0 -123
  92. package/src/list-group/files/__name@dasherize__/__name@dasherize__.e2e-spec.ts.template +8 -9
  93. package/src/list-group/files/__name@dasherize__/__name@dasherize__.html.template +13 -47
  94. package/src/list-group/files/__name@dasherize__/__name@dasherize__.spec.ts.template +46 -24
  95. package/src/list-group/files/__name@dasherize__/__name@dasherize__.ts.template +97 -39
  96. package/src/list-group/schema.json +19 -4
  97. package/src/listbox/files/__name@dasherize__/__name@dasherize__.css.template +3 -37
  98. package/src/listbox/files/__name@dasherize__/__name@dasherize__.html.template +2 -2
  99. package/src/listbox/files/__name@dasherize__/__name@dasherize__.ts.template +3 -1
  100. package/src/listbox/schema.json +19 -4
  101. package/src/menu-button/files/__name@dasherize__/__name@dasherize__.css.template +7 -47
  102. package/src/menu-button/files/__name@dasherize__/__name@dasherize__.html.template +3 -3
  103. package/src/menu-button/files/__name@dasherize__/__name@dasherize__.ts.template +10 -7
  104. package/src/menu-button/schema.json +19 -4
  105. package/src/meter/files/__name@dasherize__/__name@dasherize__.css.template +0 -12
  106. package/src/meter/files/__name@dasherize__/__name@dasherize__.html.template +2 -2
  107. package/src/meter/files/__name@dasherize__/__name@dasherize__.ts.template +3 -1
  108. package/src/meter/schema.json +19 -4
  109. package/src/navbar/files/__name@dasherize__/__name@dasherize__.css.template +6 -62
  110. package/src/navbar/schema.json +19 -4
  111. package/src/navigation-menu/files/__name@dasherize__/__name@dasherize__.css.template +6 -37
  112. package/src/navigation-menu/files/__name@dasherize__/__name@dasherize__.html.template +7 -6
  113. package/src/navigation-menu/files/__name@dasherize__/__name@dasherize__.ts.template +15 -1
  114. package/src/navigation-menu/schema.json +19 -4
  115. package/src/ng-add/index.d.ts +1 -1
  116. package/src/ng-add/index.js +2 -72
  117. package/src/ng-add/index.js.map +1 -1
  118. package/src/ng-add/index.ts +3 -86
  119. package/src/ng-add/schema.d.ts +0 -1
  120. package/src/ng-add/schema.json +0 -5
  121. package/src/ng-add/schema.ts +0 -1
  122. package/src/offcanvas/files/__name@dasherize__/__name@dasherize__.css.template +3 -70
  123. package/src/offcanvas/schema.json +19 -4
  124. package/src/pagination/files/__name@dasherize__/__name@dasherize__.css.template +2 -33
  125. package/src/pagination/files/__name@dasherize__/__name@dasherize__.html.template +6 -6
  126. package/src/pagination/files/__name@dasherize__/__name@dasherize__.ts.template +7 -1
  127. package/src/pagination/schema.json +19 -4
  128. package/src/popover/files/__name@dasherize__/__name@dasherize__.css.template +8 -69
  129. package/src/popover/schema.json +19 -4
  130. package/src/progress-bar/files/__name@dasherize__/__name@dasherize__.css.template +1 -31
  131. package/src/progress-bar/files/__name@dasherize__/__name@dasherize__.html.template +3 -3
  132. package/src/progress-bar/files/__name@dasherize__/__name@dasherize__.ts.template +5 -1
  133. package/src/progress-bar/schema.json +19 -4
  134. package/src/radio-group/files/__name@dasherize__/__name@dasherize__.css.template +4 -31
  135. package/src/radio-group/files/__name@dasherize__/__name@dasherize__.html.template +2 -2
  136. package/src/radio-group/files/__name@dasherize__/__name@dasherize__.ts.template +2 -1
  137. package/src/radio-group/schema.json +19 -4
  138. package/src/rating/files/__name@dasherize__/__name@dasherize__.css.template +17 -0
  139. package/src/rating/files/__name@dasherize__/__name@dasherize__.html.template +34 -0
  140. package/src/rating/files/__name@dasherize__/__name@dasherize__.spec.ts.template +38 -0
  141. package/src/rating/files/__name@dasherize__/__name@dasherize__.ts.template +75 -0
  142. package/src/rating/index.d.ts +1 -0
  143. package/src/rating/index.js +6 -0
  144. package/src/rating/index.js.map +1 -0
  145. package/src/rating/index.ts +3 -0
  146. package/src/rating/schema.d.ts +1 -0
  147. package/src/rating/schema.js +3 -0
  148. package/src/rating/schema.js.map +1 -0
  149. package/src/rating/schema.json +44 -0
  150. package/src/rating/schema.ts +1 -0
  151. package/src/select/files/__name@dasherize__/__name@dasherize__.css.template +4 -55
  152. package/src/select/schema.json +19 -4
  153. package/src/skeleton/files/__name@dasherize__/__name@dasherize__.css.template +2 -29
  154. package/src/skeleton/files/__name@dasherize__/__name@dasherize__.ts.template +1 -3
  155. package/src/skeleton/schema.json +19 -4
  156. package/src/skip-link/files/__name@dasherize__/__name@dasherize__.css.template +2 -14
  157. package/src/skip-link/files/__name@dasherize__/__name@dasherize__.html.template +2 -2
  158. package/src/skip-link/files/__name@dasherize__/__name@dasherize__.ts.template +5 -2
  159. package/src/skip-link/schema.json +19 -4
  160. package/src/slider/files/__name@dasherize__/__name@dasherize__.css.template +6 -20
  161. package/src/slider/files/__name@dasherize__/__name@dasherize__.html.template +2 -2
  162. package/src/slider/files/__name@dasherize__/__name@dasherize__.ts.template +3 -1
  163. package/src/slider/schema.json +19 -4
  164. package/src/spinbutton/files/__name@dasherize__/__name@dasherize__.css.template +6 -35
  165. package/src/spinbutton/files/__name@dasherize__/__name@dasherize__.html.template +4 -4
  166. package/src/spinbutton/files/__name@dasherize__/__name@dasherize__.ts.template +5 -1
  167. package/src/spinbutton/schema.json +19 -4
  168. package/src/spinner/files/__name@dasherize__/__name@dasherize__.css.template +0 -43
  169. package/src/spinner/files/__name@dasherize__/__name@dasherize__.ts.template +2 -5
  170. package/src/spinner/schema.json +19 -4
  171. package/src/steps/files/__name@dasherize__/__name@dasherize__.css.template +36 -0
  172. package/src/steps/files/__name@dasherize__/__name@dasherize__.html.template +44 -0
  173. package/src/steps/files/__name@dasherize__/__name@dasherize__.spec.ts.template +35 -0
  174. package/src/steps/files/__name@dasherize__/__name@dasherize__.ts.template +107 -0
  175. package/src/steps/index.d.ts +1 -0
  176. package/src/steps/index.js +6 -0
  177. package/src/steps/index.js.map +1 -0
  178. package/src/steps/index.ts +3 -0
  179. package/src/steps/schema.d.ts +1 -0
  180. package/src/steps/schema.js +3 -0
  181. package/src/steps/schema.js.map +1 -0
  182. package/src/steps/schema.json +44 -0
  183. package/src/steps/schema.ts +1 -0
  184. package/src/switch/files/__name@dasherize__/__name@dasherize__.css.template +7 -22
  185. package/src/switch/schema.json +19 -4
  186. package/src/table/files/__name@dasherize__/__name@dasherize__.css.template +0 -25
  187. package/src/table/files/__name@dasherize__/__name@dasherize__.html.template +3 -3
  188. package/src/table/files/__name@dasherize__/__name@dasherize__.ts.template +3 -0
  189. package/src/table/schema.json +19 -4
  190. package/src/tabs/files/__name@dasherize__/__name@dasherize__.css.template +5 -44
  191. package/src/tabs/files/__name@dasherize__/__name@dasherize__.html.template +2 -2
  192. package/src/tabs/files/__name@dasherize__/__name@dasherize__.ts.template +2 -0
  193. package/src/tabs/schema.json +19 -4
  194. package/src/textarea/files/__name@dasherize__/__name@dasherize__.css.template +2 -59
  195. package/src/textarea/schema.json +19 -4
  196. package/src/toast/files/__name@dasherize__/__name@dasherize__.css.template +1 -35
  197. package/src/toast/files/__name@dasherize__/__name@dasherize__.html.template +4 -4
  198. package/src/toast/files/__name@dasherize__/__name@dasherize__.ts.template +5 -1
  199. package/src/toast/schema.json +19 -4
  200. package/src/toolbar/files/__name@dasherize__/__name@dasherize__.css.template +2 -36
  201. package/src/toolbar/files/__name@dasherize__/__name@dasherize__.html.template +3 -3
  202. package/src/toolbar/files/__name@dasherize__/__name@dasherize__.ts.template +11 -8
  203. package/src/toolbar/schema.json +19 -4
  204. package/src/tooltip/files/__name@dasherize__/__name@dasherize__.css.template +1 -32
  205. package/src/tooltip/schema.json +19 -4
  206. package/src/tree-view/files/__name@dasherize__/__name@dasherize__.css.template +5 -27
  207. package/src/tree-view/files/__name@dasherize__/__name@dasherize__.html.template +3 -3
  208. package/src/tree-view/files/__name@dasherize__/__name@dasherize__.ts.template +16 -13
  209. package/src/tree-view/schema.json +19 -4
  210. package/src/utils/generate-component.js +3 -1
  211. package/src/utils/generate-component.js.map +1 -1
  212. package/src/utils/generate-component.ts +3 -1
  213. package/src/utils/generate-composition.js +0 -1
  214. package/src/utils/generate-composition.js.map +1 -1
  215. package/src/utils/generate-composition.ts +0 -1
  216. package/src/utils/schema-types.d.ts +1 -0
  217. package/src/utils/schema-types.ts +1 -0
  218. package/README.pt-BR.md +0 -330
@@ -1,59 +1,22 @@
1
1
  :host {
2
- --semmet-color-primary: #18181b;
3
- --semmet-color-on-primary: #ffffff;
4
- --semmet-color-surface: #ffffff;
5
- --semmet-color-surface-muted: #f4f4f5;
6
- --semmet-color-outline: #d4d4d8;
7
- --semmet-color-on-surface: #27272a;
8
- --semmet-color-on-surface-variant: #71717a;
9
- --semmet-color-danger: #b42318;
10
- --semmet-radius-sm: 8px;
11
- --semmet-space-2xs: 8px;
12
- --semmet-space-xs: 16px;
13
- --semmet-target-lg: 48px;
14
- --semmet-motion: 160ms cubic-bezier(0.2, 0, 0, 1);
15
-
16
2
  display: block;
17
- font-family: Roboto, system-ui, -apple-system, 'Segoe UI', sans-serif;
18
- font-size: 0.9375rem;
19
3
  }
20
4
 
21
5
  .semmet-input-group__label {
22
6
  display: inline-block;
23
- margin-block-end: var(--semmet-space-2xs);
24
- color: var(--semmet-color-on-surface);
25
- font-weight: 650;
26
- }
27
-
28
- .semmet-input-group__required {
29
- color: var(--semmet-color-danger);
30
7
  }
31
8
 
32
9
  .semmet-input-group {
33
10
  display: flex;
34
11
  align-items: stretch;
35
12
  width: 100%;
36
- min-height: var(--semmet-target-lg);
37
- border: 1px solid var(--semmet-color-outline);
38
- border-radius: var(--semmet-radius-sm);
39
- overflow: hidden;
40
- color: var(--semmet-color-on-surface);
41
- background: var(--semmet-color-surface);
42
- transition:
43
- border-color var(--semmet-motion),
44
- box-shadow var(--semmet-motion),
45
- opacity var(--semmet-motion);
46
13
  }
47
14
 
48
15
  .semmet-input-group:focus-within {
49
- outline: 2px solid var(--semmet-color-primary);
16
+ outline: 2px solid currentColor;
50
17
  outline-offset: 2px;
51
18
  }
52
19
 
53
- .semmet-input-group--invalid {
54
- border-color: var(--semmet-color-danger);
55
- }
56
-
57
20
  .semmet-input-group--disabled {
58
21
  opacity: 0.58;
59
22
  }
@@ -63,29 +26,15 @@
63
26
  display: inline-flex;
64
27
  align-items: center;
65
28
  justify-content: center;
66
- padding: 0 var(--semmet-space-xs);
67
29
  white-space: nowrap;
68
30
  }
69
31
 
70
- .semmet-input-group__addon {
71
- color: var(--semmet-color-on-surface-variant);
72
- background: var(--semmet-color-surface-muted);
73
- border-inline-end: 1px solid var(--semmet-color-outline);
74
- }
75
-
76
- .semmet-input-group__control + .semmet-input-group__addon {
77
- border-inline-start: 1px solid var(--semmet-color-outline);
78
- border-inline-end: 0;
79
- }
80
-
81
32
  .semmet-input-group__control {
82
33
  min-width: 0;
83
34
  flex: 1 1 auto;
84
- border: 0;
85
35
  color: inherit;
86
36
  background: transparent;
87
37
  font: inherit;
88
- padding: var(--semmet-space-2xs) var(--semmet-space-xs);
89
38
  }
90
39
 
91
40
  .semmet-input-group__control:focus {
@@ -93,12 +42,7 @@
93
42
  }
94
43
 
95
44
  .semmet-input-group__button {
96
- border: 0;
97
- border-inline-start: 1px solid var(--semmet-color-outline);
98
- color: var(--semmet-color-on-primary);
99
- background: var(--semmet-color-primary);
100
45
  font: inherit;
101
- font-weight: 650;
102
46
  cursor: pointer;
103
47
  }
104
48
 
@@ -108,15 +52,5 @@
108
52
 
109
53
  .semmet-input-group__hint,
110
54
  .semmet-input-group__error {
111
- margin: var(--semmet-space-2xs) 0 0;
112
- font-size: 0.875rem;
113
- line-height: 1.4;
114
- }
115
-
116
- .semmet-input-group__hint {
117
- color: var(--semmet-color-on-surface-variant);
118
- }
119
-
120
- .semmet-input-group__error {
121
- color: var(--semmet-color-danger);
55
+ margin: 0;
122
56
  }
@@ -1,9 +1,13 @@
1
- <!-- Semmet Angular: Input Group - native input with addon text announced through aria-describedby. -->
1
+ <!-- Semmet Angular: Input Group - native input with projected addons announced through aria-describedby. -->
2
2
  <!--
3
3
  Usage from a parent component template:
4
- Import <%= classify(name) %> in that parent component.
4
+ Import <%= classify(name) %>, <%= classify(name) %>Prefix, and <%= classify(name) %>Suffix in that parent component.
5
5
 
6
- <<%= selector %> label="Website" prefix="https://" suffix=".com" [(value)]="website" />
6
+ <<%= selector %> label="Search" type="search" [(value)]="query">
7
+ <ng-template <%= camelize(name) %>Prefix>
8
+ <svg aria-hidden="true" viewBox="0 0 20 20"><path d="M8.5 3a5.5 5.5 0 0 1 4.3 8.9l3.15 3.15-1.4 1.4-3.15-3.15A5.5 5.5 0 1 1 8.5 3Zm0 2a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7Z" /></svg>
9
+ </ng-template>
10
+ </<%= selector %>>
7
11
  -->
8
12
  <label class="semmet-input-group__label" [for]="instanceId">
9
13
  {{ label() }}
@@ -18,7 +22,9 @@ Import <%= classify(name) %> in that parent component.
18
22
  >
19
23
  @if (hasPrefix()) {
20
24
  <span class="semmet-input-group__addon" [id]="instanceId + '-prefix'">
21
- {{ prefix() }}
25
+ @if (prefix(); as prefixSlot) {
26
+ <ng-container [ngTemplateOutlet]="prefixSlot.templateRef" />
27
+ }
22
28
  </span>
23
29
  }
24
30
  <input
@@ -35,7 +41,9 @@ Import <%= classify(name) %> in that parent component.
35
41
  />
36
42
  @if (hasSuffix()) {
37
43
  <span class="semmet-input-group__addon" [id]="instanceId + '-suffix'">
38
- {{ suffix() }}
44
+ @if (suffix(); as suffixSlot) {
45
+ <ng-container [ngTemplateOutlet]="suffixSlot.templateRef" />
46
+ }
39
47
  </span>
40
48
  }
41
49
  @if (hasAction()) {
@@ -1,23 +1,38 @@
1
- import { Component, booleanAttribute, computed, input, model, output } from '@angular/core';
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import { Component, Directive, TemplateRef, booleanAttribute, computed, contentChild, inject, input, model, output } from '@angular/core';
2
3
 
3
4
  type <%= classify(name) %>InputType = 'text' | 'email' | 'search' | 'tel' | 'url';
4
5
 
5
6
  let nextId = 0;
6
7
 
8
+ @Directive({
9
+ selector: 'ng-template[<%= camelize(name) %>Prefix]',
10
+ })
11
+ export class <%= classify(name) %>Prefix {
12
+ readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);
13
+ }
14
+
15
+ @Directive({
16
+ selector: 'ng-template[<%= camelize(name) %>Suffix]',
17
+ })
18
+ export class <%= classify(name) %>Suffix {
19
+ readonly templateRef = inject<TemplateRef<unknown>>(TemplateRef);
20
+ }
21
+
7
22
  @Component({
8
23
  selector: '<%= selector %>',
9
- imports: [],
24
+ imports: [NgTemplateOutlet],
10
25
  templateUrl: './<%= dasherize(name) %>.html',
11
26
  styleUrl: './<%= dasherize(name) %>.css',
12
27
  })
13
28
  export class <%= classify(name) %> {
29
+ protected readonly prefix = contentChild(<%= classify(name) %>Prefix);
30
+ protected readonly suffix = contentChild(<%= classify(name) %>Suffix);
14
31
  protected readonly instanceId = `<%= dasherize(name) %>-${nextId++}`;
15
32
 
16
33
  readonly label = input('Website');
17
34
  readonly type = input<<%= classify(name) %>InputType>('url');
18
35
  readonly placeholder = input('example');
19
- readonly prefix = input('https://');
20
- readonly suffix = input('.com');
21
36
  readonly buttonLabel = input('Apply');
22
37
  readonly hint = input('Use a short, memorable address.');
23
38
  readonly errorMessage = input('');
@@ -26,8 +41,8 @@ export class <%= classify(name) %> {
26
41
  readonly value = model('');
27
42
  readonly buttonClick = output<MouseEvent>();
28
43
 
29
- protected readonly hasPrefix = computed(() => this.prefix().trim().length > 0);
30
- protected readonly hasSuffix = computed(() => this.suffix().trim().length > 0);
44
+ protected readonly hasPrefix = computed(() => Boolean(this.prefix()));
45
+ protected readonly hasSuffix = computed(() => Boolean(this.suffix()));
31
46
  protected readonly hasAction = computed(() => this.buttonLabel().trim().length > 0);
32
47
  protected readonly hasError = computed(() => this.errorMessage().trim().length > 0);
33
48
 
@@ -9,21 +9,36 @@
9
9
  "name": {
10
10
  "type": "string",
11
11
  "description": "The name for the new component. Used to derive the class name, selector, and file names.",
12
- "$default": { "$source": "argv", "index": 0 },
12
+ "$default": {
13
+ "$source": "argv",
14
+ "index": 0
15
+ },
13
16
  "x-prompt": "What name would you like to use for the input group component?"
14
17
  },
18
+ "e2e": {
19
+ "type": "boolean",
20
+ "default": false,
21
+ "description": "Generate a Playwright e2e spec for this component. Requires Playwright to be installed/configured in the consuming app."
22
+ },
15
23
  "path": {
16
24
  "type": "string",
17
25
  "format": "path",
18
- "$default": { "$source": "workingDirectory" },
26
+ "$default": {
27
+ "$source": "workingDirectory"
28
+ },
19
29
  "description": "The path where the component files should be created, relative to the workspace root. Defaults to the project's source root.",
20
30
  "visible": false
21
31
  },
22
32
  "project": {
23
33
  "type": "string",
24
34
  "description": "The name of the project to add the component to.",
25
- "$default": { "$source": "projectName" }
35
+ "$default": {
36
+ "$source": "projectName"
37
+ }
26
38
  }
27
39
  },
28
- "required": ["name", "project"]
40
+ "required": [
41
+ "name",
42
+ "project"
43
+ ]
29
44
  }
@@ -1,30 +1,6 @@
1
1
  :host {
2
- --semmet-color-outline: #d4d4d8;
3
- --semmet-color-on-surface: #18181b;
4
- --semmet-color-on-surface-variant: #52525b;
5
- --semmet-space-xs: 16px;
6
- --semmet-space-sm: 24px;
7
-
8
2
  display: grid;
9
3
  grid-template-columns: 1fr;
10
- gap: var(--semmet-space-sm);
11
- font-family: Roboto, system-ui, -apple-system, 'Segoe UI', sans-serif;
12
- color: var(--semmet-color-on-surface);
13
- }
14
-
15
- header,
16
- nav,
17
- footer {
18
- padding: var(--semmet-space-xs) 0;
19
- }
20
-
21
- header {
22
- border-bottom: 1px solid var(--semmet-color-outline);
23
- }
24
-
25
- footer {
26
- border-top: 1px solid var(--semmet-color-outline);
27
- color: var(--semmet-color-on-surface-variant);
28
4
  }
29
5
 
30
6
  main {
@@ -15,13 +15,13 @@ Import <%= classify(name) %> in that parent component.
15
15
  <header>
16
16
  <ng-content select="[header]"></ng-content>
17
17
  </header>
18
- <nav aria-label="Main">
18
+ <nav [attr.aria-label]="navigationLabel()">
19
19
  <ng-content select="[nav]"></ng-content>
20
20
  </nav>
21
21
  <main>
22
22
  <ng-content></ng-content>
23
23
  </main>
24
- <aside aria-label="Related links">
24
+ <aside [attr.aria-label]="asideLabel()">
25
25
  <ng-content select="[aside]"></ng-content>
26
26
  </aside>
27
27
  <footer>
@@ -1,4 +1,4 @@
1
- import { Component } from '@angular/core';
1
+ import { Component, input } from '@angular/core';
2
2
 
3
3
  @Component({
4
4
  selector: '<%= selector %>',
@@ -6,4 +6,7 @@ import { Component } from '@angular/core';
6
6
  templateUrl: './<%= dasherize(name) %>.html',
7
7
  styleUrl: './<%= dasherize(name) %>.css',
8
8
  })
9
- export class <%= classify(name) %> {}
9
+ export class <%= classify(name) %> {
10
+ readonly navigationLabel = input('Main');
11
+ readonly asideLabel = input('Related links');
12
+ }
@@ -9,21 +9,36 @@
9
9
  "name": {
10
10
  "type": "string",
11
11
  "description": "The name for the new component. Used to derive the class name, selector, and file names.",
12
- "$default": { "$source": "argv", "index": 0 },
12
+ "$default": {
13
+ "$source": "argv",
14
+ "index": 0
15
+ },
13
16
  "x-prompt": "What name would you like to use for the layout component?"
14
17
  },
18
+ "e2e": {
19
+ "type": "boolean",
20
+ "default": false,
21
+ "description": "Generate a Playwright e2e spec for this component. Requires Playwright to be installed/configured in the consuming app."
22
+ },
15
23
  "path": {
16
24
  "type": "string",
17
25
  "format": "path",
18
- "$default": { "$source": "workingDirectory" },
26
+ "$default": {
27
+ "$source": "workingDirectory"
28
+ },
19
29
  "description": "The path where the component files should be created, relative to the workspace root. Defaults to the project's source root.",
20
30
  "visible": false
21
31
  },
22
32
  "project": {
23
33
  "type": "string",
24
34
  "description": "The name of the project to add the component to.",
25
- "$default": { "$source": "projectName" }
35
+ "$default": {
36
+ "$source": "projectName"
37
+ }
26
38
  }
27
39
  },
28
- "required": ["name", "project"]
40
+ "required": [
41
+ "name",
42
+ "project"
43
+ ]
29
44
  }
@@ -1,123 +0,0 @@
1
- :host {
2
- --semmet-color-primary: #18181b;
3
- --semmet-color-on-primary: #ffffff;
4
- --semmet-color-surface: #ffffff;
5
- --semmet-color-surface-muted: #f4f4f5;
6
- --semmet-color-outline: #d4d4d8;
7
- --semmet-color-on-surface: #27272a;
8
- --semmet-color-on-surface-variant: #71717a;
9
- --semmet-radius-md: 10px;
10
- --semmet-space-3xs: 4px;
11
- --semmet-space-2xs: 8px;
12
- --semmet-space-xs: 16px;
13
- --semmet-space-xl: 64px;
14
- --semmet-target-sm: 32px;
15
- --semmet-motion: 160ms cubic-bezier(0.2, 0, 0, 1);
16
-
17
- display: block;
18
- font-family: Roboto, system-ui, -apple-system, 'Segoe UI', sans-serif;
19
- font-size: 0.9375rem;
20
- }
21
-
22
- .semmet-list-group {
23
- display: grid;
24
- margin: 0;
25
- padding: 0;
26
- overflow: hidden;
27
- border: 1px solid var(--semmet-color-outline);
28
- border-radius: var(--semmet-radius-md);
29
- background: var(--semmet-color-surface);
30
- list-style: none;
31
- }
32
-
33
- .semmet-list-group--flush {
34
- border-radius: 0;
35
- }
36
-
37
- .semmet-list-group__item + .semmet-list-group__item {
38
- border-block-start: 1px solid var(--semmet-color-outline);
39
- }
40
-
41
- .semmet-list-group__action {
42
- display: flex;
43
- align-items: center;
44
- justify-content: space-between;
45
- gap: var(--semmet-space-xs);
46
- width: 100%;
47
- min-height: var(--semmet-space-xl);
48
- padding: var(--semmet-space-xs);
49
- border: 0;
50
- color: var(--semmet-color-on-surface);
51
- background: var(--semmet-color-surface);
52
- font: inherit;
53
- text-align: start;
54
- text-decoration: none;
55
- cursor: pointer;
56
- transition:
57
- background-color var(--semmet-motion),
58
- color var(--semmet-motion),
59
- opacity var(--semmet-motion);
60
- }
61
-
62
- .semmet-list-group__action:hover:not(:disabled):not(.semmet-list-group__action--disabled) {
63
- background: var(--semmet-color-surface-muted);
64
- }
65
-
66
- .semmet-list-group__action--active {
67
- color: var(--semmet-color-on-primary);
68
- background: var(--semmet-color-primary);
69
- }
70
-
71
- .semmet-list-group__action:disabled,
72
- .semmet-list-group__action--disabled {
73
- cursor: not-allowed;
74
- opacity: 0.54;
75
- }
76
-
77
- .semmet-list-group__action:focus-visible {
78
- position: relative;
79
- z-index: 1;
80
- outline: 2px solid var(--semmet-color-primary);
81
- outline-offset: -2px;
82
- }
83
-
84
- .semmet-list-group__content {
85
- display: grid;
86
- min-width: 0;
87
- gap: var(--semmet-space-3xs);
88
- }
89
-
90
- .semmet-list-group__title {
91
- font-weight: 700;
92
- line-height: 1.25;
93
- }
94
-
95
- .semmet-list-group__description {
96
- color: var(--semmet-color-on-surface-variant);
97
- font-size: 0.875rem;
98
- line-height: 1.4;
99
- }
100
-
101
- .semmet-list-group__action--active .semmet-list-group__description {
102
- color: rgba(255, 255, 255, 0.76);
103
- }
104
-
105
- .semmet-list-group__badge {
106
- display: inline-flex;
107
- align-items: center;
108
- justify-content: center;
109
- min-width: var(--semmet-target-sm);
110
- min-height: var(--semmet-target-sm);
111
- padding: var(--semmet-space-3xs) var(--semmet-space-2xs);
112
- border-radius: 999px;
113
- color: var(--semmet-color-on-primary);
114
- background: var(--semmet-color-primary);
115
- font-size: 0.75rem;
116
- font-weight: 700;
117
- line-height: 1;
118
- }
119
-
120
- .semmet-list-group__action--active .semmet-list-group__badge {
121
- color: var(--semmet-color-primary);
122
- background: var(--semmet-color-on-primary);
123
- }
@@ -4,23 +4,22 @@ test.describe('<%= classify(name) %>', () => {
4
4
  test('updates mounted list group active action', async ({ page }) => {
5
5
  await page.goto('/');
6
6
 
7
- const component = page.locator('<%= selector %>').first();
7
+ const component = page.locator('[<%= camelize(name) %>]').first();
8
8
  test.skip(
9
9
  (await component.count()) === 0,
10
- 'Mount <<%= selector %> /> in a route or host component to enable this generated e2e test.'
10
+ 'Mount a <%= camelize(name) %> list in a route or host component to enable this generated e2e test.'
11
11
  );
12
12
 
13
- const list = component.locator('ul').first();
14
- const actions = component.locator('.semmet-list-group__action');
13
+ const items = component.locator('[<%= camelize(name) %>Item]');
15
14
  test.skip(
16
- (await actions.count()) < 2,
15
+ (await items.count()) < 2,
17
16
  'Mount at least two list group actions to enable this generated list-group e2e test.'
18
17
  );
19
18
 
20
- await expect(list).toHaveAttribute('aria-label', /.+/);
21
- await expect(actions.first()).toHaveAttribute('aria-current', /page|true/);
19
+ await expect(component).toHaveAttribute('aria-label', /.+/);
20
+ await expect(items.first()).toHaveAttribute('aria-current', /page|true/);
22
21
 
23
- await actions.nth(1).click();
24
- await expect(actions.nth(1)).toHaveAttribute('aria-current', /page|true/);
22
+ await items.nth(1).click();
23
+ await expect(items.nth(1)).toHaveAttribute('aria-current', /page|true/);
25
24
  });
26
25
  });
@@ -1,53 +1,19 @@
1
- <!-- Semmet Angular: List Group - semantic list with optional action and active states. -->
1
+ <!-- Semmet Angular: List Group - headless list relationship directives. -->
2
2
  <!--
3
3
  Usage from a parent component template:
4
- Import <%= classify(name) %> in that parent component.
4
+ Import <%= classify(name) %> and <%= classify(name) %>Item in that parent component.
5
5
 
6
- <<%= selector %> label="Settings sections" />
7
- -->
8
- <ul [id]="instanceId" [class]="listClasses()" [attr.aria-label]="label()">
9
- @for (item of items(); track item.id) {
10
- <li class="semmet-list-group__item">
11
- @if (item.href) {
12
- <a
13
- class="semmet-list-group__action"
14
- [class.semmet-list-group__action--active]="isActive(item)"
15
- [class.semmet-list-group__action--disabled]="item.disabled"
16
- [href]="item.disabled ? null : item.href"
17
- [attr.aria-current]="isActive(item) ? 'page' : null"
18
- [attr.aria-disabled]="item.disabled ? 'true' : null"
19
- (click)="select(item)"
20
- >
21
- <span class="semmet-list-group__content">
22
- <span class="semmet-list-group__title">{{ item.title }}</span>
23
- @if (item.description) {
24
- <span class="semmet-list-group__description">{{ item.description }}</span>
25
- }
26
- </span>
27
- @if (item.badge) {
28
- <span class="semmet-list-group__badge">{{ item.badge }}</span>
29
- }
30
- </a>
31
- } @else {
32
- <button
33
- type="button"
34
- class="semmet-list-group__action"
35
- [class.semmet-list-group__action--active]="isActive(item)"
36
- [disabled]="item.disabled"
37
- [attr.aria-current]="isActive(item) ? 'true' : null"
38
- (click)="select(item)"
39
- >
40
- <span class="semmet-list-group__content">
41
- <span class="semmet-list-group__title">{{ item.title }}</span>
42
- @if (item.description) {
43
- <span class="semmet-list-group__description">{{ item.description }}</span>
44
- }
45
- </span>
46
- @if (item.badge) {
47
- <span class="semmet-list-group__badge">{{ item.badge }}</span>
48
- }
49
- </button>
50
- }
6
+ <ul <%= camelize(name) %> label="Settings sections" [(activeId)]="activeSection">
7
+ @for (item of sections; track item.id) {
8
+ <li
9
+ <%= camelize(name) %>Item
10
+ [value]="item.id"
11
+ [disabled]="item.disabled"
12
+ #sectionItem="<%= camelize(name) %>Item"
13
+ [class.active]="sectionItem.active()"
14
+ >
15
+ <a [href]="item.href">{{ item.label }}</a>
51
16
  </li>
52
17
  }
53
18
  </ul>
19
+ -->