ngwr 12.2.0 → 13.0.1

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 (208) hide show
  1. package/README.md +11 -1
  2. package/border-glow/border-glow.scss +1 -1
  3. package/border-glow/styles/_index.scss +15 -233
  4. package/border-glow/styles/_rules.scss +228 -0
  5. package/breadcrumbs/breadcrumbs.scss +1 -1
  6. package/breadcrumbs/styles/_index.scss +15 -78
  7. package/breadcrumbs/styles/_rules.scss +84 -0
  8. package/card/card.scss +1 -1
  9. package/card/styles/_index.scss +15 -96
  10. package/card/styles/_rules.scss +96 -0
  11. package/cascader/cascader.scss +1 -1
  12. package/cascader/styles/_index.scss +15 -244
  13. package/cascader/styles/_rules.scss +261 -0
  14. package/checkbox/styles/_index.scss +7 -0
  15. package/circular-text/circular-text.scss +1 -1
  16. package/circular-text/styles/_index.scss +15 -63
  17. package/circular-text/styles/_rules.scss +58 -0
  18. package/color-picker/styles/_index.scss +8 -0
  19. package/drag-drop/sortable-list.scss +1 -1
  20. package/drag-drop/styles/_index.scss +14 -143
  21. package/drag-drop/styles/_rules.scss +151 -0
  22. package/falling-text/falling-text.scss +1 -1
  23. package/falling-text/styles/_index.scss +15 -36
  24. package/falling-text/styles/_rules.scss +31 -0
  25. package/fesm2022/ngwr-border-glow.mjs +14 -5
  26. package/fesm2022/ngwr-border-glow.mjs.map +1 -1
  27. package/fesm2022/ngwr-breadcrumbs.mjs +15 -4
  28. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  29. package/fesm2022/ngwr-card.mjs +2 -2
  30. package/fesm2022/ngwr-card.mjs.map +1 -1
  31. package/fesm2022/ngwr-cascader.mjs +27 -9
  32. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  33. package/fesm2022/ngwr-checkbox.mjs +86 -8
  34. package/fesm2022/ngwr-checkbox.mjs.map +1 -1
  35. package/fesm2022/ngwr-circular-text.mjs +2 -2
  36. package/fesm2022/ngwr-circular-text.mjs.map +1 -1
  37. package/fesm2022/ngwr-color-picker.mjs +57 -7
  38. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  39. package/fesm2022/ngwr-context-menu.mjs +6 -2
  40. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  41. package/fesm2022/ngwr-date-picker.mjs +8 -0
  42. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  43. package/fesm2022/ngwr-dialog.mjs +22 -16
  44. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  45. package/fesm2022/ngwr-directives.mjs +5 -2
  46. package/fesm2022/ngwr-directives.mjs.map +1 -1
  47. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  48. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  49. package/fesm2022/ngwr-drawer.mjs +24 -18
  50. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  51. package/fesm2022/ngwr-dropdown.mjs +6 -2
  52. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  53. package/fesm2022/ngwr-falling-text.mjs +2 -2
  54. package/fesm2022/ngwr-falling-text.mjs.map +1 -1
  55. package/fesm2022/ngwr-file-upload.mjs +29 -8
  56. package/fesm2022/ngwr-file-upload.mjs.map +1 -1
  57. package/fesm2022/ngwr-form.mjs +48 -1
  58. package/fesm2022/ngwr-form.mjs.map +1 -1
  59. package/fesm2022/ngwr-fuzzy-text.mjs +21 -4
  60. package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
  61. package/fesm2022/ngwr-glitch-text.mjs +2 -2
  62. package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
  63. package/fesm2022/ngwr-gradient-text.mjs +11 -4
  64. package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
  65. package/fesm2022/ngwr-icon-adapters-feather.mjs +11 -0
  66. package/fesm2022/ngwr-icon-adapters-feather.mjs.map +1 -1
  67. package/fesm2022/ngwr-icon-adapters-lucide.mjs +22 -2
  68. package/fesm2022/ngwr-icon-adapters-lucide.mjs.map +1 -1
  69. package/fesm2022/ngwr-icon.mjs +474 -37
  70. package/fesm2022/ngwr-icon.mjs.map +1 -1
  71. package/fesm2022/ngwr-input-otp.mjs +41 -3
  72. package/fesm2022/ngwr-input-otp.mjs.map +1 -1
  73. package/fesm2022/ngwr-knob.mjs +17 -2
  74. package/fesm2022/ngwr-knob.mjs.map +1 -1
  75. package/fesm2022/ngwr-lightbox.mjs +2 -2
  76. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  77. package/fesm2022/ngwr-list.mjs +2 -2
  78. package/fesm2022/ngwr-list.mjs.map +1 -1
  79. package/fesm2022/ngwr-loading-bar.mjs +2 -2
  80. package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
  81. package/fesm2022/ngwr-markdown.mjs +63 -11
  82. package/fesm2022/ngwr-markdown.mjs.map +1 -1
  83. package/fesm2022/ngwr-marquee.mjs +2 -2
  84. package/fesm2022/ngwr-marquee.mjs.map +1 -1
  85. package/fesm2022/ngwr-overlay.mjs +36 -7
  86. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  87. package/fesm2022/ngwr-pagination.mjs +1 -1
  88. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  89. package/fesm2022/ngwr-qr.mjs +38 -1
  90. package/fesm2022/ngwr-qr.mjs.map +1 -1
  91. package/fesm2022/ngwr-radio.mjs +63 -8
  92. package/fesm2022/ngwr-radio.mjs.map +1 -1
  93. package/fesm2022/ngwr-rating.mjs +17 -2
  94. package/fesm2022/ngwr-rating.mjs.map +1 -1
  95. package/fesm2022/ngwr-segmented.mjs +22 -3
  96. package/fesm2022/ngwr-segmented.mjs.map +1 -1
  97. package/fesm2022/ngwr-select.mjs +46 -12
  98. package/fesm2022/ngwr-select.mjs.map +1 -1
  99. package/fesm2022/ngwr-shiny-text.mjs +12 -5
  100. package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
  101. package/fesm2022/ngwr-slider.mjs +21 -6
  102. package/fesm2022/ngwr-slider.mjs.map +1 -1
  103. package/fesm2022/ngwr-spotlight-card.mjs +2 -2
  104. package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
  105. package/fesm2022/ngwr-star-border.mjs +2 -2
  106. package/fesm2022/ngwr-star-border.mjs.map +1 -1
  107. package/fesm2022/ngwr-switch.mjs +44 -4
  108. package/fesm2022/ngwr-switch.mjs.map +1 -1
  109. package/fesm2022/ngwr-table.mjs +1 -1
  110. package/fesm2022/ngwr-table.mjs.map +1 -1
  111. package/fesm2022/ngwr-tabs.mjs +6 -2
  112. package/fesm2022/ngwr-tabs.mjs.map +1 -1
  113. package/fesm2022/ngwr-textarea.mjs +5 -2
  114. package/fesm2022/ngwr-textarea.mjs.map +1 -1
  115. package/fesm2022/ngwr-theme.mjs +41 -1
  116. package/fesm2022/ngwr-theme.mjs.map +1 -1
  117. package/fesm2022/ngwr-tilt-card.mjs +2 -2
  118. package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
  119. package/fesm2022/ngwr-transfer.mjs +38 -6
  120. package/fesm2022/ngwr-transfer.mjs.map +1 -1
  121. package/fesm2022/ngwr-tree.mjs +33 -7
  122. package/fesm2022/ngwr-tree.mjs.map +1 -1
  123. package/fesm2022/ngwr-typewriter.mjs +2 -2
  124. package/fesm2022/ngwr-typewriter.mjs.map +1 -1
  125. package/fesm2022/ngwr-utils.mjs +107 -1
  126. package/fesm2022/ngwr-utils.mjs.map +1 -1
  127. package/fesm2022/ngwr-version.mjs +1 -1
  128. package/fesm2022/ngwr-version.mjs.map +1 -1
  129. package/fesm2022/ngwr-virtual-scroll.mjs +2 -2
  130. package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
  131. package/fesm2022/ngwr-waves.mjs +2 -2
  132. package/fesm2022/ngwr-waves.mjs.map +1 -1
  133. package/file-upload/styles/_index.scss +6 -0
  134. package/glitch-text/glitch-text.scss +1 -1
  135. package/glitch-text/styles/_index.scss +14 -164
  136. package/glitch-text/styles/_rules.scss +160 -0
  137. package/gradient-text/gradient-text.scss +1 -1
  138. package/gradient-text/styles/_index.scss +15 -118
  139. package/gradient-text/styles/_rules.scss +113 -0
  140. package/input/styles/_index.scss +13 -0
  141. package/input-otp/styles/_index.scss +8 -0
  142. package/lightbox/lightbox.scss +1 -1
  143. package/lightbox/styles/_index.scss +15 -191
  144. package/lightbox/styles/_rules.scss +198 -0
  145. package/list/list.scss +1 -1
  146. package/list/styles/_index.scss +15 -101
  147. package/list/styles/_rules.scss +108 -0
  148. package/llms-full.txt +4 -4
  149. package/loading-bar/loading-bar.scss +1 -1
  150. package/loading-bar/styles/_index.scss +15 -33
  151. package/loading-bar/styles/_rules.scss +28 -0
  152. package/marquee/marquee.scss +1 -1
  153. package/marquee/styles/_index.scss +15 -155
  154. package/marquee/styles/_rules.scss +150 -0
  155. package/package.json +3 -3
  156. package/segmented/styles/_index.scss +8 -0
  157. package/select/styles/_index.scss +17 -1
  158. package/shiny-text/shiny-text.scss +1 -1
  159. package/shiny-text/styles/_index.scss +14 -105
  160. package/shiny-text/styles/_rules.scss +101 -0
  161. package/slider/styles/_index.scss +8 -0
  162. package/spotlight-card/spotlight-card.scss +1 -1
  163. package/spotlight-card/styles/_index.scss +15 -52
  164. package/spotlight-card/styles/_rules.scss +47 -0
  165. package/star-border/star-border.scss +1 -1
  166. package/star-border/styles/_index.scss +15 -125
  167. package/star-border/styles/_rules.scss +120 -0
  168. package/switch/styles/_index.scss +7 -0
  169. package/theme/styles/_dark.scss +81 -4
  170. package/theme/styles/_index.scss +1 -0
  171. package/theme/styles/_motion.scss +94 -0
  172. package/tilt-card/styles/_index.scss +15 -45
  173. package/tilt-card/styles/_rules.scss +40 -0
  174. package/tilt-card/tilt-card.scss +1 -1
  175. package/tree/styles/_index.scss +15 -1
  176. package/types/ngwr-breadcrumbs.d.ts +1 -0
  177. package/types/ngwr-cascader.d.ts +17 -1
  178. package/types/ngwr-checkbox.d.ts +51 -3
  179. package/types/ngwr-color-picker.d.ts +19 -1
  180. package/types/ngwr-file-upload.d.ts +18 -1
  181. package/types/ngwr-form.d.ts +51 -2
  182. package/types/ngwr-fuzzy-text.d.ts +5 -0
  183. package/types/ngwr-icon-adapters-feather.d.ts +11 -0
  184. package/types/ngwr-icon.d.ts +42 -1
  185. package/types/ngwr-input-otp.d.ts +23 -1
  186. package/types/ngwr-knob.d.ts +14 -0
  187. package/types/ngwr-radio.d.ts +37 -2
  188. package/types/ngwr-rating.d.ts +14 -0
  189. package/types/ngwr-segmented.d.ts +18 -1
  190. package/types/ngwr-select.d.ts +17 -1
  191. package/types/ngwr-shiny-text.d.ts +1 -0
  192. package/types/ngwr-slider.d.ts +14 -1
  193. package/types/ngwr-switch.d.ts +26 -2
  194. package/types/ngwr-textarea.d.ts +3 -0
  195. package/types/ngwr-theme.d.ts +24 -0
  196. package/types/ngwr-transfer.d.ts +17 -1
  197. package/types/ngwr-tree.d.ts +21 -1
  198. package/types/ngwr-utils.d.ts +47 -1
  199. package/types/ngwr-version.d.ts +1 -1
  200. package/typewriter/styles/_index.scss +15 -38
  201. package/typewriter/styles/_rules.scss +33 -0
  202. package/typewriter/typewriter.scss +1 -1
  203. package/virtual-scroll/styles/_index.scss +15 -32
  204. package/virtual-scroll/styles/_rules.scss +27 -0
  205. package/virtual-scroll/virtual-scroll.scss +1 -1
  206. package/waves/styles/_index.scss +15 -50
  207. package/waves/styles/_rules.scss +45 -0
  208. package/waves/waves.scss +1 -1
@@ -1,191 +1,15 @@
1
- // Image with click-to-zoom lightbox. The host wraps the `<img>` and is
2
- // sized by the consumer (CSS / inline styles on `<wr-lightbox>`).
3
-
4
- @use '../../theme/styles' as theme;
5
-
6
- .wr-lightbox {
7
- display: inline-block;
8
- position: relative;
9
- overflow: hidden;
10
- @include theme.smooth-br(var(--wr-lightbox-radius, var(--wr-border-radius-base)));
11
- background: var(--wr-color-hover);
12
- // No `cursor: zoom-in` here: `disablePreview` renders a plain thumbnail with no
13
- // trigger and nothing to open, and the zoom cursor invited a click that did
14
- // nothing. `&__trigger` carries it — that is the element that opens the viewer.
15
-
16
- // Reserve space before the image resolves so the box doesn't collapse to
17
- // 0 and shove the layout when the thumbnail pops in.
18
- &--loading {
19
- min-height: var(--wr-lightbox-loading-min-height, 4rem);
20
- }
21
-
22
- &--loading::after {
23
- content: '';
24
- position: absolute;
25
- inset: 0;
26
- // Sit above the host's empty placeholder background and below the image,
27
- // so the shimmer is visible over the reserved area while loading.
28
- background: linear-gradient(
29
- 90deg,
30
- rgba(var(--wr-color-surface-rgb), 0) 0%,
31
- rgba(var(--wr-color-surface-rgb), 0.45) 50%,
32
- rgba(var(--wr-color-surface-rgb), 0) 100%
33
- );
34
- background-size: 200% 100%;
35
- animation: wr-lightbox-shimmer 1.4s linear infinite;
36
- pointer-events: none;
37
- z-index: 1;
38
- }
39
-
40
- &__trigger {
41
- display: block;
42
- width: 100%;
43
- height: 100%;
44
- padding: 0;
45
- margin: 0;
46
- border: 0;
47
- background: transparent;
48
- cursor: zoom-in;
49
-
50
- // Not cancelled — MOVED. The ring is drawn on the host by
51
- // `&:has(&__trigger:focus-visible)` below (see the comment there); this
52
- // only keeps the UA's own ring from leaking a few clipped corner pixels
53
- // through in a second colour.
54
- &:focus-visible {
55
- outline: none;
56
- }
57
- }
58
-
59
- &__thumb {
60
- display: block;
61
- width: 100%;
62
- height: 100%;
63
- object-fit: cover;
64
- user-select: none;
65
- -webkit-user-drag: none;
66
- // Fade in once the `loaded` signal drops the `--loading` class, so the
67
- // image resolves smoothly instead of snapping in. Sits above the shimmer.
68
- position: relative;
69
- z-index: 2;
70
- opacity: 1;
71
- transition: opacity 0.25s ease;
72
- }
73
-
74
- &--loading &__thumb {
75
- opacity: 0;
76
- }
77
-
78
- // The trigger is `width: 100%; height: 100%`, so it is exactly coterminous
79
- // with the host — and the host clips (`overflow: hidden` above, for the
80
- // rounded corners), so a ring drawn on the button falls entirely outside the
81
- // clip and nothing survives. Insetting the offset does not rescue it either:
82
- // `&__thumb` is `position: relative; z-index: 2` and paints over the button's
83
- // own outline. An element's outline is not clipped by its OWN `overflow`, so
84
- // the ring goes on the host instead.
85
- &:has(&__trigger:focus-visible) {
86
- @include theme.focus-ring;
87
- }
88
- }
89
-
90
- @keyframes wr-lightbox-shimmer {
91
- // `background-position` offsets are physical by spec — there is no logical
92
- // form to convert to, so nothing here is being suppressed. The sweep is also
93
- // aesthetic choreography rather than layout, and the gradient it rides
94
- // (`--loading::after`) is symmetric about its midpoint, so a sweep that keeps
95
- // running left-to-right under RTL reads as a highlight, not a broken layout.
96
- // rtl-ok: background-position has no logical equivalent — see above
97
- from {
98
- background-position: 200% 0;
99
- }
100
- to {
101
- background-position: -200% 0;
102
- }
103
- }
104
-
105
- .wr-lightbox-backdrop {
106
- background: rgba(var(--wr-color-backdrop-rgb), 0.85);
107
- }
108
-
109
- .wr-lightbox-overlay {
110
- pointer-events: auto;
111
- }
112
-
113
- .wr-lightbox-viewer {
114
- display: flex;
115
- flex-direction: column;
116
- align-items: center;
117
- gap: 1rem;
118
- max-width: 95vw;
119
- max-height: 95vh;
120
- max-height: 95dvh;
121
- padding: 1rem;
122
- animation: wr-lightbox-viewer-in 0.18s ease;
123
- outline: none;
124
- // Own the swipe-down-to-dismiss gesture; no scroll/zoom to defer to.
125
- touch-action: none;
126
-
127
- &__close {
128
- --wr-icon-size: 1.25rem;
129
- position: absolute;
130
- top: 1rem;
131
- inset-inline-end: 1rem;
132
- display: inline-flex;
133
- align-items: center;
134
- justify-content: center;
135
- width: 2.25rem;
136
- height: 2.25rem;
137
- padding: 0;
138
- border: 0;
139
- border-radius: 999px;
140
- background: rgba(var(--wr-color-surface-rgb), 0.12);
141
- color: rgba(var(--wr-color-surface-rgb), 0.9);
142
- cursor: pointer;
143
- transition:
144
- background 0.15s ease,
145
- transform 0.15s ease;
146
-
147
- @include theme.touch-target($positioned: true); // 36px -> 44px tap area on touch
148
-
149
- &:hover {
150
- background: rgba(var(--wr-color-surface-rgb), 0.2);
151
- }
152
-
153
- &:active {
154
- transform: scale(0.95);
155
- }
156
-
157
- &:focus-visible {
158
- outline: 2px solid rgba(var(--wr-color-surface-rgb), 0.9);
159
- outline-offset: 2px;
160
- }
161
- }
162
-
163
- &__full {
164
- display: block;
165
- max-width: 100%;
166
- max-height: calc(95vh - 4rem);
167
- max-height: calc(95dvh - 4rem);
168
- object-fit: contain;
169
- cursor: zoom-out;
170
- @include theme.smooth-br(0.5rem);
171
- }
172
-
173
- &__caption {
174
- color: rgba(var(--wr-color-surface-rgb), 0.85);
175
- font-family: var(--wr-font-family-base);
176
- font-size: var(--wr-text-sm);
177
- text-align: center;
178
- max-width: 60ch;
179
- }
180
- }
181
-
182
- @keyframes wr-lightbox-viewer-in {
183
- from {
184
- opacity: 0;
185
- transform: scale(0.96);
186
- }
187
- to {
188
- opacity: 1;
189
- transform: scale(1);
190
- }
191
- }
1
+ // Public Sass entry for `@use 'ngwr/lightbox'`.
2
+ //
3
+ // Pulls the whole theme so a standalone import still brings in every design
4
+ // token these rules reference, then loads the rules themselves from `_rules`.
5
+ //
6
+ // The split is what keeps the token layer out of the JavaScript bundle.
7
+ // `lightbox.scss` is the component's `styleUrl`, and a component stylesheet is
8
+ // its OWN Sass compilation — `@use` only deduplicates within one. So while the
9
+ // umbrella sheet emits the theme once, forwarding it from here would inline a
10
+ // second, byte-identical copy of `:root`, `[data-theme='dark']` and the
11
+ // box-sizing reset into the compiled component styles, which ng-packagr then
12
+ // embeds in the FESM bundle as a string. `lightbox.scss` forwards `_rules`
13
+ // instead, so it carries this component's own CSS and nothing else.
14
+ @use '../../theme/styles';
15
+ @forward 'rules';
@@ -0,0 +1,198 @@
1
+ // Image with click-to-zoom lightbox. The host wraps the `<img>` and is
2
+ // sized by the consumer (CSS / inline styles on `<wr-lightbox>`).
3
+
4
+ @use '../../theme/styles/mixins' as theme;
5
+ // `focus` is the one theme partial these rules still load that emits CSS of its
6
+ // own — the shared ring mixin lives in the same file as the baseline
7
+ // `.wr-*:focus-visible` rules, and there is no mixin-only module to take it from.
8
+ // That is ~4 KB of rules identical to the global sheet's, against the ~24 KB token
9
+ // layer the split removes, and it is the honest trade: hand-rolling the three
10
+ // declarations here is what the shared mixin exists to prevent.
11
+ @use '../../theme/styles/focus';
12
+
13
+ .wr-lightbox {
14
+ display: inline-block;
15
+ position: relative;
16
+ overflow: hidden;
17
+ @include theme.smooth-br(var(--wr-lightbox-radius, var(--wr-border-radius-base)));
18
+ background: var(--wr-color-hover);
19
+ // No `cursor: zoom-in` here: `disablePreview` renders a plain thumbnail with no
20
+ // trigger and nothing to open, and the zoom cursor invited a click that did
21
+ // nothing. `&__trigger` carries it — that is the element that opens the viewer.
22
+
23
+ // Reserve space before the image resolves so the box doesn't collapse to
24
+ // 0 and shove the layout when the thumbnail pops in.
25
+ &--loading {
26
+ min-height: var(--wr-lightbox-loading-min-height, 4rem);
27
+ }
28
+
29
+ &--loading::after {
30
+ content: '';
31
+ position: absolute;
32
+ inset: 0;
33
+ // Sit above the host's empty placeholder background and below the image,
34
+ // so the shimmer is visible over the reserved area while loading.
35
+ background: linear-gradient(
36
+ 90deg,
37
+ rgba(var(--wr-color-surface-rgb), 0) 0%,
38
+ rgba(var(--wr-color-surface-rgb), 0.45) 50%,
39
+ rgba(var(--wr-color-surface-rgb), 0) 100%
40
+ );
41
+ background-size: 200% 100%;
42
+ animation: wr-lightbox-shimmer 1.4s linear infinite;
43
+ pointer-events: none;
44
+ z-index: 1;
45
+ }
46
+
47
+ &__trigger {
48
+ display: block;
49
+ width: 100%;
50
+ height: 100%;
51
+ padding: 0;
52
+ margin: 0;
53
+ border: 0;
54
+ background: transparent;
55
+ cursor: zoom-in;
56
+
57
+ // Not cancelled — MOVED. The ring is drawn on the host by
58
+ // `&:has(&__trigger:focus-visible)` below (see the comment there); this
59
+ // only keeps the UA's own ring from leaking a few clipped corner pixels
60
+ // through in a second colour.
61
+ &:focus-visible {
62
+ outline: none;
63
+ }
64
+ }
65
+
66
+ &__thumb {
67
+ display: block;
68
+ width: 100%;
69
+ height: 100%;
70
+ object-fit: cover;
71
+ user-select: none;
72
+ -webkit-user-drag: none;
73
+ // Fade in once the `loaded` signal drops the `--loading` class, so the
74
+ // image resolves smoothly instead of snapping in. Sits above the shimmer.
75
+ position: relative;
76
+ z-index: 2;
77
+ opacity: 1;
78
+ transition: opacity 0.25s ease;
79
+ }
80
+
81
+ &--loading &__thumb {
82
+ opacity: 0;
83
+ }
84
+
85
+ // The trigger is `width: 100%; height: 100%`, so it is exactly coterminous
86
+ // with the host — and the host clips (`overflow: hidden` above, for the
87
+ // rounded corners), so a ring drawn on the button falls entirely outside the
88
+ // clip and nothing survives. Insetting the offset does not rescue it either:
89
+ // `&__thumb` is `position: relative; z-index: 2` and paints over the button's
90
+ // own outline. An element's outline is not clipped by its OWN `overflow`, so
91
+ // the ring goes on the host instead.
92
+ &:has(&__trigger:focus-visible) {
93
+ @include focus.focus-ring;
94
+ }
95
+ }
96
+
97
+ @keyframes wr-lightbox-shimmer {
98
+ // `background-position` offsets are physical by spec — there is no logical
99
+ // form to convert to, so nothing here is being suppressed. The sweep is also
100
+ // aesthetic choreography rather than layout, and the gradient it rides
101
+ // (`--loading::after`) is symmetric about its midpoint, so a sweep that keeps
102
+ // running left-to-right under RTL reads as a highlight, not a broken layout.
103
+ // rtl-ok: background-position has no logical equivalent — see above
104
+ from {
105
+ background-position: 200% 0;
106
+ }
107
+ to {
108
+ background-position: -200% 0;
109
+ }
110
+ }
111
+
112
+ .wr-lightbox-backdrop {
113
+ background: rgba(var(--wr-color-backdrop-rgb), 0.85);
114
+ }
115
+
116
+ .wr-lightbox-overlay {
117
+ pointer-events: auto;
118
+ }
119
+
120
+ .wr-lightbox-viewer {
121
+ display: flex;
122
+ flex-direction: column;
123
+ align-items: center;
124
+ gap: 1rem;
125
+ max-width: 95vw;
126
+ max-height: 95vh;
127
+ max-height: 95dvh;
128
+ padding: 1rem;
129
+ animation: wr-lightbox-viewer-in 0.18s ease;
130
+ outline: none;
131
+ // Own the swipe-down-to-dismiss gesture; no scroll/zoom to defer to.
132
+ touch-action: none;
133
+
134
+ &__close {
135
+ --wr-icon-size: 1.25rem;
136
+ position: absolute;
137
+ top: 1rem;
138
+ inset-inline-end: 1rem;
139
+ display: inline-flex;
140
+ align-items: center;
141
+ justify-content: center;
142
+ width: 2.25rem;
143
+ height: 2.25rem;
144
+ padding: 0;
145
+ border: 0;
146
+ border-radius: 999px;
147
+ background: rgba(var(--wr-color-surface-rgb), 0.12);
148
+ color: rgba(var(--wr-color-surface-rgb), 0.9);
149
+ cursor: pointer;
150
+ transition:
151
+ background 0.15s ease,
152
+ transform 0.15s ease;
153
+
154
+ @include theme.touch-target($positioned: true); // 36px -> 44px tap area on touch
155
+
156
+ &:hover {
157
+ background: rgba(var(--wr-color-surface-rgb), 0.2);
158
+ }
159
+
160
+ &:active {
161
+ transform: scale(0.95);
162
+ }
163
+
164
+ &:focus-visible {
165
+ outline: 2px solid rgba(var(--wr-color-surface-rgb), 0.9);
166
+ outline-offset: 2px;
167
+ }
168
+ }
169
+
170
+ &__full {
171
+ display: block;
172
+ max-width: 100%;
173
+ max-height: calc(95vh - 4rem);
174
+ max-height: calc(95dvh - 4rem);
175
+ object-fit: contain;
176
+ cursor: zoom-out;
177
+ @include theme.smooth-br(0.5rem);
178
+ }
179
+
180
+ &__caption {
181
+ color: rgba(var(--wr-color-surface-rgb), 0.85);
182
+ font-family: var(--wr-font-family-base);
183
+ font-size: var(--wr-text-sm);
184
+ text-align: center;
185
+ max-width: 60ch;
186
+ }
187
+ }
188
+
189
+ @keyframes wr-lightbox-viewer-in {
190
+ from {
191
+ opacity: 0;
192
+ transform: scale(0.96);
193
+ }
194
+ to {
195
+ opacity: 1;
196
+ transform: scale(1);
197
+ }
198
+ }
package/list/list.scss CHANGED
@@ -1 +1 @@
1
- @forward './styles';
1
+ @forward './styles/rules';
@@ -1,101 +1,15 @@
1
- // Generic list. The container holds `<ul>`; rows are flex layouts with
2
- // three slots (leading / body / trailing). Modifiers cascade from the
3
- // container via the `&--bordered` / `&--dividers` / `&--dense` parent
4
- // classes.
5
-
6
- @use '../../theme/styles' as theme;
7
-
8
- .wr-list {
9
- --wr-list-item-padding-y: 0.625rem;
10
- --wr-list-item-padding-x: 1rem;
11
- --wr-list-item-gap: 0.75rem;
12
- --wr-list-divider-color: var(--wr-color-outline);
13
- --wr-list-bg: transparent;
14
- --wr-list-hover-bg: var(--wr-color-hover);
15
- --wr-list-active-bg: rgba(var(--wr-color-primary-rgb), 0.08);
16
-
17
- display: block;
18
- font-family: var(--wr-font-family-base);
19
- font-size: var(--wr-text-sm);
20
- color: var(--wr-color-on-surface);
21
- background: var(--wr-list-bg);
22
-
23
- &__items {
24
- list-style: none;
25
- margin: 0;
26
- padding: 0;
27
- }
28
-
29
- // Container modifiers
30
-
31
- &--bordered {
32
- border: 1px solid var(--wr-list-divider-color);
33
- @include theme.smooth-br(var(--wr-border-radius-base));
34
- overflow: hidden;
35
- }
36
-
37
- &--dividers .wr-list__item:not(:last-child) {
38
- border-bottom: 1px solid var(--wr-list-divider-color);
39
- }
40
-
41
- &--dense {
42
- --wr-list-item-padding-y: 0.375rem;
43
- }
44
-
45
- // Item layout
46
-
47
- &__item {
48
- display: flex;
49
- align-items: center;
50
- gap: var(--wr-list-item-gap);
51
- padding: calc(var(--wr-list-item-padding-y) * var(--wr-density-y, 1))
52
- calc(var(--wr-list-item-padding-x) * var(--wr-density-x, 1));
53
- color: inherit;
54
- transition: background 0.12s ease;
55
-
56
- &--interactive {
57
- cursor: pointer;
58
-
59
- &:hover {
60
- background: var(--wr-list-hover-bg);
61
- }
62
-
63
- &:active {
64
- background: var(--wr-list-active-bg);
65
- }
66
-
67
- &:focus-visible {
68
- @include theme.focus-ring;
69
- outline-offset: -2px;
70
- }
71
- }
72
-
73
- &--disabled {
74
- opacity: var(--wr-disabled-opacity);
75
- pointer-events: none;
76
- cursor: not-allowed;
77
- }
78
- }
79
-
80
- &__leading,
81
- &__trailing {
82
- display: inline-flex;
83
- align-items: center;
84
- flex: 0 0 auto;
85
- color: rgba(var(--wr-color-on-surface-rgb), 0.65);
86
-
87
- &:empty {
88
- display: none;
89
- }
90
- }
91
-
92
- &__body {
93
- flex: 1 1 auto;
94
- min-width: 0;
95
-
96
- // Allow long single-line labels to truncate cleanly.
97
- overflow: hidden;
98
- text-overflow: ellipsis;
99
- white-space: nowrap;
100
- }
101
- }
1
+ // Public Sass entry for `@use 'ngwr/list'`.
2
+ //
3
+ // Pulls the whole theme so a standalone import still brings in every design
4
+ // token these rules reference, then loads the rules themselves from `_rules`.
5
+ //
6
+ // The split is what keeps the token layer out of the JavaScript bundle.
7
+ // `list.scss` is the component's `styleUrl`, and a component stylesheet is
8
+ // its OWN Sass compilation — `@use` only deduplicates within one. So while the
9
+ // umbrella sheet emits the theme once, forwarding it from here would inline a
10
+ // second, byte-identical copy of `:root`, `[data-theme='dark']` and the
11
+ // box-sizing reset into the compiled component styles, which ng-packagr then
12
+ // embeds in the FESM bundle as a string. `list.scss` forwards `_rules`
13
+ // instead, so it carries this component's own CSS and nothing else.
14
+ @use '../../theme/styles';
15
+ @forward 'rules';
@@ -0,0 +1,108 @@
1
+ // Generic list. The container holds `<ul>`; rows are flex layouts with
2
+ // three slots (leading / body / trailing). Modifiers cascade from the
3
+ // container via the `&--bordered` / `&--dividers` / `&--dense` parent
4
+ // classes.
5
+
6
+ @use '../../theme/styles/mixins' as theme;
7
+ // `focus` is the one theme partial these rules still load that emits CSS of its
8
+ // own — the shared ring mixin lives in the same file as the baseline
9
+ // `.wr-*:focus-visible` rules, and there is no mixin-only module to take it from.
10
+ // That is ~4 KB of rules identical to the global sheet's, against the ~24 KB token
11
+ // layer the split removes, and it is the honest trade: hand-rolling the three
12
+ // declarations here is what the shared mixin exists to prevent.
13
+ @use '../../theme/styles/focus';
14
+
15
+ .wr-list {
16
+ --wr-list-item-padding-y: 0.625rem;
17
+ --wr-list-item-padding-x: 1rem;
18
+ --wr-list-item-gap: 0.75rem;
19
+ --wr-list-divider-color: var(--wr-color-outline);
20
+ --wr-list-bg: transparent;
21
+ --wr-list-hover-bg: var(--wr-color-hover);
22
+ --wr-list-active-bg: rgba(var(--wr-color-primary-rgb), 0.08);
23
+
24
+ display: block;
25
+ font-family: var(--wr-font-family-base);
26
+ font-size: var(--wr-text-sm);
27
+ color: var(--wr-color-on-surface);
28
+ background: var(--wr-list-bg);
29
+
30
+ &__items {
31
+ list-style: none;
32
+ margin: 0;
33
+ padding: 0;
34
+ }
35
+
36
+ // Container modifiers
37
+
38
+ &--bordered {
39
+ border: 1px solid var(--wr-list-divider-color);
40
+ @include theme.smooth-br(var(--wr-border-radius-base));
41
+ overflow: hidden;
42
+ }
43
+
44
+ &--dividers .wr-list__item:not(:last-child) {
45
+ border-bottom: 1px solid var(--wr-list-divider-color);
46
+ }
47
+
48
+ &--dense {
49
+ --wr-list-item-padding-y: 0.375rem;
50
+ }
51
+
52
+ // Item layout
53
+
54
+ &__item {
55
+ display: flex;
56
+ align-items: center;
57
+ gap: var(--wr-list-item-gap);
58
+ padding: calc(var(--wr-list-item-padding-y) * var(--wr-density-y, 1))
59
+ calc(var(--wr-list-item-padding-x) * var(--wr-density-x, 1));
60
+ color: inherit;
61
+ transition: background 0.12s ease;
62
+
63
+ &--interactive {
64
+ cursor: pointer;
65
+
66
+ &:hover {
67
+ background: var(--wr-list-hover-bg);
68
+ }
69
+
70
+ &:active {
71
+ background: var(--wr-list-active-bg);
72
+ }
73
+
74
+ &:focus-visible {
75
+ @include focus.focus-ring;
76
+ outline-offset: -2px;
77
+ }
78
+ }
79
+
80
+ &--disabled {
81
+ opacity: var(--wr-disabled-opacity);
82
+ pointer-events: none;
83
+ cursor: not-allowed;
84
+ }
85
+ }
86
+
87
+ &__leading,
88
+ &__trailing {
89
+ display: inline-flex;
90
+ align-items: center;
91
+ flex: 0 0 auto;
92
+ color: rgba(var(--wr-color-on-surface-rgb), 0.65);
93
+
94
+ &:empty {
95
+ display: none;
96
+ }
97
+ }
98
+
99
+ &__body {
100
+ flex: 1 1 auto;
101
+ min-width: 0;
102
+
103
+ // Allow long single-line labels to truncate cleanly.
104
+ overflow: hidden;
105
+ text-overflow: ellipsis;
106
+ white-space: nowrap;
107
+ }
108
+ }
package/llms-full.txt CHANGED
@@ -262,7 +262,7 @@
262
262
  - import: `import { WrDatePicker } from 'ngwr/date-picker'`
263
263
  - selector: `wr-date-picker`, `wr-date-range-picker`
264
264
  - exports: WrDatePicker, WrDateRangePicker, WrDateRange
265
- - Unified date / time / date-time picker. `<input>` + popover for every mode — overlay content swaps based on `[mode]`. Parses on every keystroke (silently — only emits when valid), reformats canonical on blur. Format driven by `WrDateAdapter`.
265
+ - Unified date / time / date-time picker. `<input>` + popover for every mode — overlay content swaps based on `[mode]`. Parses on every keystroke (silently — only emits when valid), reformats canonical on blur. Format driven by `WrDateAdapter`. A signal-forms native control — it implements `FormValueControl`, so `[formField]` binds straight to its `value` model. `[(value)]` works standalone, and `[(ngModel)]` / reactive forms keep working through Angular's bridge.
266
266
 
267
267
  ## ngwr/date-picker/testing
268
268
  - import: `import { WrDatePickerDayHarness } from 'ngwr/date-picker/testing'`
@@ -394,8 +394,8 @@
394
394
  ## ngwr/form
395
395
  - import: `import { WrFormItem } from 'ngwr/form'`
396
396
  - selector: `wr-form-error`, `wr-form-field`, `wr-form-item`
397
- - exports: WrFormItem, WrFormField, WrFormError, WR_FORM_FIELD, WrFormFieldContext, WR_FORM_ERRORS, WR_FORM_ERROR_FALLBACKS, provideWrFormErrors, WrFormErrorContext, WrFormErrorMessage, WrFormErrorMessages
398
- - Layout helpers: <wr-form-item> wraps a label + control + error message; <wr-form-error> renders inline error text.
397
+ - exports: WrFormItem, WrFormField, WrFormError, WR_FORM_FIELD, WrFormFieldContext, useFormFieldAria, WrFormFieldAria, WR_FORM_ERRORS, WR_FORM_ERROR_FALLBACKS, provideWrFormErrors, WrFormErrorContext, WrFormErrorMessage, WrFormErrorMessages
398
+ - `<wr-form-item>` — the bare layout wrapper: it stacks a label, a control and an error message, and colours them red when you tell it to. It reads nothing about the control. Its richer sibling `<wr-form-field>` has its own page, and is the one to reach for by default.
399
399
 
400
400
  ## ngwr/form/testing
401
401
  - import: `import { WrFormFieldHarness } from 'ngwr/form/testing'`
@@ -1007,7 +1007,7 @@
1007
1007
 
1008
1008
  ## ngwr/utils
1009
1009
  - import: `import { isDefined } from 'ngwr/utils'`
1010
- - exports: Maybe, SafeAny, isDefined, isNonEmptyArray, isObservable, clamp, round, numAttr, resolveCssSize, ResolveCssSizeOptions, ResolvedCssSize, getRootFontSize, getFocusableElements, trapFocus, randomId, noop, debounce, throttle, WrDebouncedFn, WrThrottledFn, KEYS, hasModifier, isPrintableKey, WrKey, badgeLog
1010
+ - exports: Maybe, SafeAny, isDefined, isNonEmptyArray, isObservable, clamp, round, numAttr, isSafeCssValue, resolveCssSize, ResolveCssSizeOptions, ResolvedCssSize, getRootFontSize, getFocusableElements, trapFocus, randomId, noop, debounce, throttle, WrDebouncedFn, WrThrottledFn, KEYS, hasModifier, isPrintableKey, WrKey, badgeLog
1011
1011
 
1012
1012
  ## ngwr/validators
1013
1013
  - import: `import { WrValidators } from 'ngwr/validators'`
@@ -1 +1 @@
1
- @forward './styles';
1
+ @forward './styles/rules';