ngwr 9.0.1 → 10.0.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 (108) hide show
  1. package/README.md +14 -0
  2. package/badge/styles/_index.scss +16 -6
  3. package/badge/styles/_tag.scss +10 -1
  4. package/button/styles/_index.scss +48 -1
  5. package/date-picker/styles/_index.scss +62 -0
  6. package/dialog/styles/_index.scss +65 -0
  7. package/drawer/styles/_index.scss +83 -0
  8. package/fesm2022/ngwr-action-sheet.mjs +1 -1
  9. package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
  10. package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
  11. package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
  12. package/fesm2022/ngwr-card.mjs +2 -2
  13. package/fesm2022/ngwr-card.mjs.map +1 -1
  14. package/fesm2022/ngwr-cascader.mjs +6 -5
  15. package/fesm2022/ngwr-cascader.mjs.map +1 -1
  16. package/fesm2022/ngwr-color-picker.mjs +6 -5
  17. package/fesm2022/ngwr-color-picker.mjs.map +1 -1
  18. package/fesm2022/ngwr-context-menu.mjs +7 -7
  19. package/fesm2022/ngwr-context-menu.mjs.map +1 -1
  20. package/fesm2022/ngwr-date-picker.mjs +521 -8
  21. package/fesm2022/ngwr-date-picker.mjs.map +1 -1
  22. package/fesm2022/ngwr-density.mjs +10 -2
  23. package/fesm2022/ngwr-density.mjs.map +1 -1
  24. package/fesm2022/ngwr-dialog.mjs +95 -13
  25. package/fesm2022/ngwr-dialog.mjs.map +1 -1
  26. package/fesm2022/ngwr-drag-drop.mjs +2 -2
  27. package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
  28. package/fesm2022/ngwr-drawer.mjs +377 -22
  29. package/fesm2022/ngwr-drawer.mjs.map +1 -1
  30. package/fesm2022/ngwr-dropdown.mjs +4 -3
  31. package/fesm2022/ngwr-dropdown.mjs.map +1 -1
  32. package/fesm2022/ngwr-i18n-en.mjs +21 -0
  33. package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
  34. package/fesm2022/ngwr-i18n-ru.mjs +22 -0
  35. package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
  36. package/fesm2022/ngwr-i18n.mjs +74 -1
  37. package/fesm2022/ngwr-i18n.mjs.map +1 -1
  38. package/fesm2022/ngwr-icon.mjs +74 -35
  39. package/fesm2022/ngwr-icon.mjs.map +1 -1
  40. package/fesm2022/ngwr-lightbox.mjs +2 -2
  41. package/fesm2022/ngwr-lightbox.mjs.map +1 -1
  42. package/fesm2022/ngwr-list.mjs +2 -2
  43. package/fesm2022/ngwr-list.mjs.map +1 -1
  44. package/fesm2022/ngwr-mention.mjs +166 -10
  45. package/fesm2022/ngwr-mention.mjs.map +1 -1
  46. package/fesm2022/ngwr-overlay.mjs +173 -3
  47. package/fesm2022/ngwr-overlay.mjs.map +1 -1
  48. package/fesm2022/ngwr-pagination.mjs +17 -4
  49. package/fesm2022/ngwr-pagination.mjs.map +1 -1
  50. package/fesm2022/ngwr-popconfirm.mjs +4 -3
  51. package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
  52. package/fesm2022/ngwr-popover.mjs +10 -3
  53. package/fesm2022/ngwr-popover.mjs.map +1 -1
  54. package/fesm2022/ngwr-select.mjs +233 -43
  55. package/fesm2022/ngwr-select.mjs.map +1 -1
  56. package/fesm2022/ngwr-table.mjs +1 -1
  57. package/fesm2022/ngwr-table.mjs.map +1 -1
  58. package/fesm2022/ngwr-theme.mjs +13 -3
  59. package/fesm2022/ngwr-theme.mjs.map +1 -1
  60. package/fesm2022/ngwr-tree.mjs +4 -3
  61. package/fesm2022/ngwr-tree.mjs.map +1 -1
  62. package/fesm2022/ngwr-version.mjs +1 -1
  63. package/fesm2022/ngwr-version.mjs.map +1 -1
  64. package/fesm2022/ngwr-waves.mjs +25 -3
  65. package/fesm2022/ngwr-waves.mjs.map +1 -1
  66. package/i18n/en.json +165 -0
  67. package/i18n/ru.json +165 -0
  68. package/icon/styles/_index.scss +10 -1
  69. package/input/styles/_index.scss +16 -0
  70. package/input-number/styles/_index.scss +8 -1
  71. package/keyboard/styles/_index.scss +10 -3
  72. package/llms-full.txt +14 -14
  73. package/llms.txt +12 -6
  74. package/mention/styles/_index.scss +23 -0
  75. package/package.json +23 -5
  76. package/pagination/styles/_index.scss +12 -0
  77. package/popover/styles/_index.scss +129 -45
  78. package/schematics/ng-add/index.js +18 -4
  79. package/schematics/package.json +3 -0
  80. package/schematics/use/symbol-map.json +7 -0
  81. package/select/styles/_index.scss +13 -0
  82. package/splitter/styles/_index.scss +7 -1
  83. package/table/styles/_index.scss +28 -10
  84. package/theme/styles/_box-model.scss +29 -0
  85. package/theme/styles/_colors.scss +74 -15
  86. package/theme/styles/_dark.scss +52 -6
  87. package/theme/styles/_index.scss +1 -0
  88. package/types/ngwr-cascader.d.ts +1 -0
  89. package/types/ngwr-color-picker.d.ts +1 -0
  90. package/types/ngwr-context-menu.d.ts +1 -0
  91. package/types/ngwr-date-picker.d.ts +172 -4
  92. package/types/ngwr-density.d.ts +8 -1
  93. package/types/ngwr-dialog.d.ts +80 -8
  94. package/types/ngwr-drawer.d.ts +245 -10
  95. package/types/ngwr-dropdown.d.ts +1 -0
  96. package/types/ngwr-i18n.d.ts +65 -2
  97. package/types/ngwr-icon.d.ts +11 -19
  98. package/types/ngwr-mention.d.ts +45 -1
  99. package/types/ngwr-overlay.d.ts +80 -2
  100. package/types/ngwr-pagination.d.ts +14 -1
  101. package/types/ngwr-popconfirm.d.ts +1 -0
  102. package/types/ngwr-popover.d.ts +1 -0
  103. package/types/ngwr-select.d.ts +121 -9
  104. package/types/ngwr-theme.d.ts +8 -1
  105. package/types/ngwr-tree.d.ts +1 -0
  106. package/types/ngwr-version.d.ts +1 -1
  107. package/types/ngwr-waves.d.ts +10 -0
  108. package/waves/styles/_index.scss +21 -0
package/llms-full.txt CHANGED
@@ -113,7 +113,7 @@
113
113
  - import: `import { WrCascader } from 'ngwr/cascader'`
114
114
  - selector: `wr-cascader`
115
115
  - exports: WrCascader, type WrCascaderOption, type WrCascaderSize
116
- - Multi-level select. Drills through hierarchical categories one column at a time; picking a leaf commits the full path. Implements `ControlValueAccessor` — model is `readonly T[]`.
116
+ - Multi-level select. Drills through hierarchical categories one column at a time; picking a leaf commits the full path. A signal-forms native control — it implements `FormValueControl`, so `[formField]` binds straight to its `value` model (`readonly T[]`). `[(value)]` works standalone, and `[(ngModel)]` / reactive forms keep working through Angular's bridge.
117
117
 
118
118
  ## ngwr/checkbox
119
119
  - import: `import { WrCheckbox } from 'ngwr/checkbox'`
@@ -195,8 +195,8 @@
195
195
 
196
196
  ## ngwr/date-picker
197
197
  - import: `import { WrDatePicker } from 'ngwr/date-picker'`
198
- - selector: `wr-date-picker`
199
- - exports: WrDatePicker
198
+ - selector: `wr-date-picker`, `wr-date-range-picker`
199
+ - exports: WrDatePicker, WrDateRangePicker, WrDateRange
200
200
  - 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`.
201
201
 
202
202
  ## ngwr/decrypt-text
@@ -218,7 +218,7 @@
218
218
 
219
219
  ## ngwr/dialog
220
220
  - import: `import { WrDialog } from 'ngwr/dialog'`
221
- - exports: WrDialog, WrDialogRef, WR_DIALOG_DATA, WrDialogOptions, WrDialogTitle, WrDialogContent, WrDialogFooter, WrDialogClose
221
+ - exports: WrDialog, WrDialogRef, WR_DIALOG_DATA, WR_DIALOG_REF, WrDialogOptions, WrDialogTitle, WrDialogContent, WrDialogFooter, WrDialogClose
222
222
  - Modal dialogs via a service that wraps @angular/cdk/dialog. Open any component as a dialog and read its close result as a Promise.
223
223
 
224
224
  ## ngwr/directives
@@ -247,8 +247,8 @@
247
247
  ## ngwr/drawer
248
248
  - import: `import { WrDrawer } from 'ngwr/drawer'`
249
249
  - selector: `wr-drawer`
250
- - exports: WrDrawer, WrDrawerTitle, WrDrawerContent, WrDrawerFooter, WrDrawerClose, WrDrawerPosition
251
- - Side panel that slides in from any edge. Two-way binds `open`; renders into a CDK overlay so it sits above page content.
250
+ - exports: WrDrawer, WrDrawerManager, WrDrawerRef, WR_DRAWER_DATA, WR_DRAWER_REF, WrDrawerTitle, WrDrawerContent, WrDrawerFooter, WrDrawerClose, WrDrawerOptions, WrDrawerPosition
251
+ - Side panel that slides in from any edge. Use the component when the markup lives in your template, or `WrDrawerManager` to open any component as a drawer and read its close result.
252
252
 
253
253
  ## ngwr/dropdown
254
254
  - import: `import { WrDropdown } from 'ngwr/dropdown'`
@@ -309,7 +309,7 @@
309
309
  ## ngwr/i18n
310
310
  - import: `import { WrI18n } from 'ngwr/i18n'`
311
311
  - selector: `[wrT]`
312
- - exports: WrI18n, WrTPipe, WrTDirective, WR_I18N_CONFIG, DEFAULT_WR_I18N_CONFIG, type WrI18nCatalog, type WrI18nConfig, type WrI18nConfigResolved, type WrI18nParams, type WrI18nMissingHandler, WR_I18N_LOADER, type WrI18nLoader, WrI18nStaticLoader, type WrI18nStaticCatalogs, type WrI18nStaticScopedCatalogs, WrI18nHttpLoader, type WrI18nHttpLoaderConfig, provideWrI18n, provideWrI18nStaticLoader, provideWrI18nHttpLoader, type ProvideWrI18nOptions, useI18nText, readI18nText, useI18nFormatter
312
+ - exports: WrI18n, WrTPipe, WrTDirective, WR_I18N_CONFIG, DEFAULT_WR_I18N_CONFIG, type WrI18nCatalog, type WrI18nConfig, type WrI18nConfigResolved, type WrI18nParams, type WrI18nMissingHandler, WR_I18N_LOADER, type WrI18nLoader, WR_I18N_BASE_CATALOGS, type WrI18nBaseCatalogs, WrI18nStaticLoader, type WrI18nStaticCatalogs, type WrI18nStaticScopedCatalogs, WrI18nHttpLoader, type WrI18nHttpLoaderConfig, provideWrI18n, provideWrI18nBaseCatalogs, provideWrI18nStaticLoader, provideWrI18nHttpLoader, type ProvideWrI18nOptions, useI18nText, readI18nText, useI18nFormatter
313
313
  - Reactive i18n service. Active locale lives on a signal, catalogs load lazily through a swappable loader (HTTP or static), and double-brace placeholders interpolate at render time. Scopes let feature modules ship and load their own catalogs.
314
314
 
315
315
  ## ngwr/icon
@@ -413,8 +413,8 @@
413
413
  - Stacked-segment progress bar. Each segment is sized proportionally to its `value` relative to the sum (or the explicit `max`); legend listed underneath.
414
414
 
415
415
  ## ngwr/overlay
416
- - import: `import { WrOverlayContainer } from 'ngwr/overlay'`
417
- - exports: WrOverlayContainer, provideWrOverlay, provideWrResponsiveOverlays, WR_OVERLAY, WR_OVERLAY_CONTAINER, WR_RESPONSIVE_OVERLAYS, wrPresentAsSheet
416
+ - import: `import { wrAppendOverlayClose } from 'ngwr/overlay'`
417
+ - exports: wrAppendOverlayClose, WrOutsideClick, WrOverlayContainer, provideWrOverlay, provideWrResponsiveOverlays, WR_OVERLAY, WR_OVERLAY_CONTAINER, WR_RESPONSIVE_OVERLAYS, wrPresentAsSheet
418
418
 
419
419
  ## ngwr/page-header
420
420
  - import: `import { WrPageHeader } from 'ngwr/page-header'`
@@ -470,7 +470,7 @@
470
470
  - import: `import { WrRadio } from 'ngwr/radio'`
471
471
  - selector: `wr-radio-group`, `wr-radio`
472
472
  - exports: WrRadio, WrRadioSize, WrRadioGroup, WR_RADIO_GROUP, type WrRadioGroupContext
473
- - Single-choice option. Always used inside <wr-radio-group>, which implements ControlValueAccessor.
473
+ - Single-choice option. Always used inside <wr-radio-group>, which is the form 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.
474
474
 
475
475
  ## ngwr/rating
476
476
  - import: `import { WrRating } from 'ngwr/rating'`
@@ -504,7 +504,7 @@
504
504
  - import: `import { WrSelect } from 'ngwr/select'`
505
505
  - selector: `wr-option-group`, `wr-option`, `wr-select`
506
506
  - exports: WrSelect, WrOption, WrOptionGroup, WR_SELECT, type WrSelectContext, WrSelectMode, WrSelectSearchLoader, WrSelectTagValidator, WrSelectSize
507
- - Native-like select built on CDK Overlay. Implements ControlValueAccessor.
507
+ - Native-like select built on CDK Overlay. 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.
508
508
 
509
509
  ## ngwr/shiny-text
510
510
  - import: `import { WrShinyText } from 'ngwr/shiny-text'`
@@ -527,7 +527,7 @@
527
527
  - import: `import { WrSlider } from 'ngwr/slider'`
528
528
  - selector: `wr-slider`
529
529
  - exports: WrSlider, WrSliderValue
530
- - Drag-to-pick numeric input. Single-thumb by default, optional dual-thumb range mode. Implements `ControlValueAccessor` so it plays nicely with template-driven and reactive forms.
530
+ - Drag-to-pick numeric input. Single-thumb by default, optional dual-thumb range mode. A signal-forms native control — it implements `FormValueControl`, so `[formField]` binds straight to its `value` model. `[(value)]` works standalone, and template-driven `[(ngModel)]` / reactive forms keep working through Angular's bridge.
531
531
 
532
532
  ## ngwr/sparkline
533
533
  - import: `import { WrSparkline } from 'ngwr/sparkline'`
@@ -600,7 +600,7 @@
600
600
  - import: `import { WrSwitch } from 'ngwr/switch'`
601
601
  - selector: `wr-switch`
602
602
  - exports: WrSwitch, WrSwitchSize
603
- - Boolean toggle with an iOS-style slider. Implements ControlValueAccessor.
603
+ - Boolean toggle with an iOS-style slider. A signal-forms native control — it implements `FormCheckboxControl`, so `[formField]` binds straight to its `checked` model. `[(checked)]` works standalone, and `[(ngModel)]` / reactive forms keep working through Angular's bridge.
604
604
 
605
605
  ## ngwr/table
606
606
  - import: `import { WrTable } from 'ngwr/table'`
@@ -618,7 +618,7 @@
618
618
  - import: `import { WrTextarea } from 'ngwr/textarea'`
619
619
  - selector: `wr-textarea`
620
620
  - exports: WrTextarea, WrTextareaSize, WrTextareaResize
621
- - Multi-line text input. Implements ControlValueAccessor. Optional autosize.
621
+ - Multi-line text input with optional autosize. 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.
622
622
 
623
623
  ## ngwr/theme
624
624
  - import: `import { WR_COLORS } from 'ngwr/theme'`
package/llms.txt CHANGED
@@ -74,10 +74,13 @@ before writing your own. Full catalog: https://ngwr.dev/reference/components.
74
74
  ## Common components (selector — import)
75
75
 
76
76
  - **Form** — `wr-btn` (ngwr/button), `wrInput` (ngwr/input), `wr-select`
77
- (ngwr/select; modes single/multi/search/tag), `wr-checkbox` (form state is
78
- `[(checked)]`; inside `<wr-checkbox-group>` the identity input is
79
- `checkboxValue`, NOT `value`), `wr-switch`, `wr-slider`, `wr-input-number`,
80
- `wr-input-otp`, `wr-date-picker` (date/time/datetime), `wr-file-upload`,
77
+ (ngwr/select; modes single/multi/search/tag, plus `searchable` for a
78
+ multi-with-typeahead and `(searchChange)` for server-side search),
79
+ `wr-checkbox` (form state is `[(checked)]`; inside `<wr-checkbox-group>` the
80
+ identity input is `checkboxValue`, NOT `value`), `wr-switch`, `wr-slider`,
81
+ `wr-input-number`, `wr-input-otp`, `wr-date-picker` (date/time/datetime) and
82
+ `wr-date-range-picker` (both in ngwr/date-picker; the range value is
83
+ `[start, end]`, hence a separate component), `wr-file-upload`,
81
84
  `wr-form-field`, `wr-color-picker`.
82
85
  - **Data** — `wr-table` (column pin/resize/drag-reorder, row selection,
83
86
  expandable rows, grouping, summary rows, CSV export, virtualized body),
@@ -89,9 +92,12 @@ before writing your own. Full catalog: https://ngwr.dev/reference/components.
89
92
  `wr-toolbar`, `wr-descriptions`, `wr-statistic`, `wr-lightbox`,
90
93
  `wr-pull-to-refresh`.
91
94
  - **Navigation** — `wr-tabs`, `wr-stepper`, `wr-breadcrumbs`, `wr-dropdown-menu`.
92
- - **Overlays** — `wr-drawer`, `wr-action-sheet`, `[wrPopover]` (directive; has a
95
+ - **Overlays** — `wr-drawer` (or `WrDrawerManager.open()` to open a component as
96
+ a drawer from code), `wr-action-sheet`, `[wrPopover]` (directive; has a
93
97
  `tooltip` mode), `wr-command-palette`, `wr-context-menu`, `wr-popconfirm`.
94
- (Dialog and toast are service-opened — inject `WrDialog` / `WrToast`.)
98
+ (Dialog and toast are service-opened — inject `WrDialog` / `WrToast`.
99
+ Content inside a service-opened dialog or drawer can `inject(WrDialogRef)` /
100
+ `inject(WrDrawerRef)` to close itself.)
95
101
 
96
102
  ## Patterns
97
103
 
@@ -4,6 +4,25 @@
4
4
  pointer-events: auto;
5
5
  }
6
6
 
7
+ // Polite live region the directive appends to `<body>`. It carries the two
8
+ // things `role="textbox"` cannot express as ARIA state — how many suggestions
9
+ // appeared, and what was inserted on commit — because `aria-expanded` is not a
10
+ // supported state of textbox.
11
+ //
12
+ // Visually hidden rather than `display: none` / `visibility: hidden`, both of
13
+ // which take the element out of the accessibility tree and silence it entirely.
14
+ .wr-mention__status {
15
+ position: absolute;
16
+ width: 1px;
17
+ height: 1px;
18
+ padding: 0;
19
+ margin: -1px;
20
+ overflow: hidden;
21
+ clip: rect(0, 0, 0, 0);
22
+ white-space: nowrap;
23
+ border: 0;
24
+ }
25
+
7
26
  .wr-mention-panel {
8
27
  display: block;
9
28
  min-width: 12rem;
@@ -38,6 +57,10 @@
38
57
  }
39
58
  }
40
59
 
60
+ // Nothing renders this any more — the panel's empty branch was unreachable
61
+ // (`activate()` closes before opening when nothing matches) and has been
62
+ // removed. Kept because `.wr-*` classes are public API and deleting one is a
63
+ // breaking change for no gain; a consumer styling it simply sees no element.
41
64
  &__empty {
42
65
  padding: 0.5rem 0.75rem;
43
66
  color: var(--wr-color-on-surface-muted);
package/package.json CHANGED
@@ -1,15 +1,31 @@
1
1
  {
2
2
  "name": "ngwr",
3
- "version": "9.0.1",
3
+ "version": "10.0.0",
4
4
  "license": "MIT",
5
- "description": "NGWR – Angular UI components library",
5
+ "description": "Signals-first Angular UI library: 100+ standalone, zoneless-ready components with native Signal Forms, SSR-safe rendering and CSS-variable theming.",
6
6
  "author": "Roman Khegay <rk@garuna.dev> (https://garuna.dev)",
7
7
  "keywords": [
8
8
  "ngwr",
9
9
  "angular",
10
- "ui",
11
- "ux",
12
- "framework",
10
+ "angular-components",
11
+ "angular-ui",
12
+ "angular-library",
13
+ "component-library",
14
+ "ui-components",
15
+ "design-system",
16
+ "signals",
17
+ "signal-forms",
18
+ "zoneless",
19
+ "standalone",
20
+ "ssr",
21
+ "accessibility",
22
+ "a11y",
23
+ "scss",
24
+ "theming",
25
+ "dark-mode",
26
+ "tree-shakable",
27
+ "data-table",
28
+ "typescript",
13
29
  "frontend"
14
30
  ],
15
31
  "homepage": "https://ngwr.dev",
@@ -52,6 +68,8 @@
52
68
  "migrations": "./schematics/migrations.json"
53
69
  },
54
70
  "exports": {
71
+ "./schematics/*": "./schematics/*",
72
+ "./i18n/*.json": "./i18n/*.json",
55
73
  ".": {
56
74
  "sass": "./styles.scss",
57
75
  "types": "./types/ngwr.d.ts",
@@ -2,6 +2,11 @@
2
2
 
3
3
  .wr-pagination {
4
4
  display: block;
5
+ // Breathing room of its own. A pager almost always sits right under a table or
6
+ // list, and with a bare `display: block` and no padding its cells touched the
7
+ // content above and below. Padding rather than margin so it stays inside the
8
+ // component's own box and can't collapse into the consumer's spacing.
9
+ padding-block: 0.5rem;
5
10
 
6
11
  &--disabled {
7
12
  opacity: 0.6;
@@ -80,6 +85,13 @@
80
85
 
81
86
  &__size {
82
87
  min-width: 0;
88
+
89
+ // The 10rem floor on `.wr-select__trigger` is sized for a standalone field.
90
+ // Here the select only ever holds "20 / page", so the pager was reserving
91
+ // 160px for a ~75px label — the single widest thing in the control.
92
+ .wr-select__trigger {
93
+ min-width: 0;
94
+ }
83
95
  }
84
96
 
85
97
  // Size variants — set the cell size; each button gets the matching [size].
@@ -1,8 +1,85 @@
1
+ @use 'sass:list';
2
+
1
3
  @use '../../theme/styles' as theme;
2
4
  @use '../../overlay/styles'; // shared .wr-overlay-sheet / .wr-overlay-backdrop for responsive mode
3
5
 
6
+ // --- Arrow -----------------------------------------------------------------
7
+ //
8
+ // A small square rotated 45°, half tucked under the panel so only the tip shows.
9
+ // Tooltip and popover share the geometry; the popover additionally carries the
10
+ // panel's border on the two outward faces so the outline reads as continuous.
11
+ //
12
+ // Placement is driven by the resolved position modifier the directive puts on the
13
+ // overlay host (`--top` means the panel sits ABOVE the trigger, so the arrow hangs
14
+ // off the panel's BOTTOM edge). All 12 positions are covered — the hand-written
15
+ // tooltip rules this replaces only handled 8, so `top-start` / `top-end` /
16
+ // `bottom-start` / `bottom-end` tooltips have been shipping with no arrow at all.
17
+ $_arrow: 6px;
18
+ $_arrow-half: 3px;
19
+ $_arrow-inset: 0.625rem; // distance from the panel corner for the -start / -end variants
20
+
21
+ // edge = which side of the panel the arrow hangs off; align = where along that side.
22
+ $_arrow-placement: (
23
+ top: (bottom, center),
24
+ top-start: (bottom, start),
25
+ top-end: (bottom, end),
26
+ bottom: (top, center),
27
+ bottom-start: (top, start),
28
+ bottom-end: (top, end),
29
+ left: (right, center),
30
+ left-start: (right, start),
31
+ left-end: (right, end),
32
+ right: (left, center),
33
+ right-start: (left, start),
34
+ right-end: (left, end),
35
+ );
36
+
37
+ /// Positions the arrow against `$edge`, offset outwards by `$pull`.
38
+ @mixin _arrow-at($edge, $align, $pull) {
39
+ #{$edge}: -$pull;
40
+
41
+ @if $edge == bottom or $edge == top {
42
+ @if $align == center {
43
+ left: 50%;
44
+ margin-left: -$_arrow-half;
45
+ } @else if $align == start {
46
+ left: $_arrow-inset;
47
+ } @else {
48
+ right: $_arrow-inset;
49
+ }
50
+ } @else {
51
+ @if $align == center {
52
+ top: 50%;
53
+ margin-top: -$_arrow-half;
54
+ } @else if $align == start {
55
+ top: $_arrow-inset;
56
+ } @else {
57
+ bottom: $_arrow-inset;
58
+ }
59
+ }
60
+ }
61
+
62
+ /// The two faces of the rotated square that stay visible outside the panel.
63
+ @mixin _arrow-border($edge) {
64
+ @if $edge == bottom {
65
+ border-right: 1px solid var(--wr-color-outline);
66
+ border-bottom: 1px solid var(--wr-color-outline);
67
+ } @else if $edge == top {
68
+ border-left: 1px solid var(--wr-color-outline);
69
+ border-top: 1px solid var(--wr-color-outline);
70
+ } @else if $edge == right {
71
+ border-top: 1px solid var(--wr-color-outline);
72
+ border-right: 1px solid var(--wr-color-outline);
73
+ } @else {
74
+ border-bottom: 1px solid var(--wr-color-outline);
75
+ border-left: 1px solid var(--wr-color-outline);
76
+ }
77
+ }
78
+
4
79
  .wr-popover-overlay {
5
80
  > * {
81
+ // Containing block for the arrow below.
82
+ position: relative;
6
83
  display: block;
7
84
  min-width: 8rem;
8
85
  max-width: 22rem;
@@ -14,6 +91,36 @@
14
91
  color: var(--wr-color-on-surface);
15
92
  animation: wr-overlay-in var(--wr-overlay-duration) var(--wr-overlay-ease);
16
93
  transform-origin: top left;
94
+
95
+ &::after {
96
+ content: '';
97
+ position: absolute;
98
+ width: $_arrow;
99
+ height: $_arrow;
100
+ background: var(--wr-color-surface);
101
+ transform: rotate(45deg);
102
+ }
103
+ }
104
+
105
+ // Responsive bottom-sheet mode has no anchor to point at, so no arrow.
106
+ &.wr-overlay-sheet > *::after {
107
+ content: none;
108
+ }
109
+ }
110
+
111
+ @each $position, $spec in $_arrow-placement {
112
+ $edge: list.nth($spec, 1);
113
+ $align: list.nth($spec, 2);
114
+
115
+ // Pulled one extra pixel so the square's own border lines up flush with the
116
+ // panel's, instead of leaving the panel border showing across the arrow's base.
117
+ .wr-popover-overlay--#{$position} > *::after {
118
+ @include _arrow-at($edge, $align, $_arrow-half + 1px);
119
+ @include _arrow-border($edge);
120
+ }
121
+
122
+ .wr-tooltip-overlay--#{$position} .wr-tooltip::after {
123
+ @include _arrow-at($edge, $align, $_arrow-half);
17
124
  }
18
125
  }
19
126
 
@@ -28,12 +135,25 @@
28
135
  }
29
136
 
30
137
  .wr-tooltip {
138
+ // Follows the theme instead of inverting against it: on a dark canvas the
139
+ // tooltip is dark, on a light canvas light. It used to invert (a light chip on
140
+ // dark), which is a common convention but reads as a foreign element here.
141
+ //
142
+ // Both halves are tokens, so an app that wants the inverted look back needs one
143
+ // rule, not an override of every tooltip rule:
144
+ // .wr-tooltip { --wr-tooltip-bg: var(--wr-color-on-surface);
145
+ // --wr-tooltip-color: var(--wr-color-dark-contrast); }
146
+ --wr-tooltip-bg: var(--wr-color-surface);
147
+ --wr-tooltip-color: var(--wr-color-on-surface);
148
+ --wr-tooltip-border: var(--wr-color-outline);
149
+
31
150
  position: relative;
32
151
  display: inline-block;
33
152
  max-width: 18rem;
34
153
  padding: 0.3125rem 0.5rem;
35
- background: var(--wr-color-on-surface);
36
- color: var(--wr-color-dark-contrast);
154
+ background: var(--wr-tooltip-bg);
155
+ color: var(--wr-tooltip-color);
156
+ border: 1px solid var(--wr-tooltip-border);
37
157
  border-radius: var(--wr-border-radius-sm);
38
158
  font-family: var(--wr-font-family-base);
39
159
  font-size: var(--wr-text-xs);
@@ -42,56 +162,20 @@
42
162
  animation: wr-overlay-in var(--wr-overlay-duration) var(--wr-overlay-ease);
43
163
  transform-origin: top left;
44
164
 
45
- // Arrow
165
+ // Arrow — geometry from the shared placement loop at the top of this file.
46
166
  &::after {
47
167
  content: '';
48
168
  position: absolute;
49
- width: 6px;
50
- height: 6px;
51
- background: var(--wr-color-on-surface);
169
+ width: $_arrow;
170
+ height: $_arrow;
171
+ background: var(--wr-tooltip-bg);
52
172
  transform: rotate(45deg);
53
173
  }
54
174
  }
55
175
 
56
- // Arrow placement is dictated by the overlay panel's position modifier
57
- // (the wr-tooltip-overlay--top|bottom|left|right class lives on the
58
- // portal host wrapping the tooltip).
59
- .wr-tooltip-overlay--top .wr-tooltip::after {
60
- left: 50%;
61
- bottom: -3px;
62
- margin-left: -3px;
63
- }
64
- .wr-tooltip-overlay--bottom .wr-tooltip::after {
65
- left: 50%;
66
- top: -3px;
67
- margin-left: -3px;
68
- }
69
- .wr-tooltip-overlay--left .wr-tooltip::after {
70
- top: 50%;
71
- right: -3px;
72
- margin-top: -3px;
73
- }
74
- .wr-tooltip-overlay--left-start .wr-tooltip::after {
75
- top: 0.625rem;
76
- right: -3px;
77
- }
78
- .wr-tooltip-overlay--left-end .wr-tooltip::after {
79
- bottom: 0.625rem;
80
- right: -3px;
81
- }
82
- .wr-tooltip-overlay--right .wr-tooltip::after {
83
- top: 50%;
84
- left: -3px;
85
- margin-top: -3px;
86
- }
87
- .wr-tooltip-overlay--right-start .wr-tooltip::after {
88
- top: 0.625rem;
89
- left: -3px;
90
- }
91
- .wr-tooltip-overlay--right-end .wr-tooltip::after {
92
- bottom: 0.625rem;
93
- left: -3px;
94
- }
176
+ // Arrow placement for both modes is generated from `$_arrow-placement` at the top
177
+ // of this file — the per-position rules that used to live here are emitted there,
178
+ // byte-identical for the 8 positions they covered plus the 4 they missed.
95
179
 
96
180
  @media (prefers-reduced-motion: reduce) {
97
181
  .wr-tooltip {
@@ -10,8 +10,17 @@ const schematics_1 = require("@angular-devkit/schematics");
10
10
  const tasks_1 = require("@angular-devkit/schematics/tasks");
11
11
  const dependencies_1 = require("@schematics/angular/utility/dependencies");
12
12
  const workspace_1 = require("@schematics/angular/utility/workspace");
13
- /** Base peers, regardless of prompt answers. */
14
- const BASE_PEERS = [['@angular/cdk', '>=22.0.0']];
13
+ /**
14
+ * Base peers, regardless of prompt answers.
15
+ *
16
+ * `lucide` is here because the bootstrap snippet this schematic prints registers
17
+ * icons through the lucide adapter — leaving it out made the very first snippet
18
+ * a consumer pastes fail to resolve.
19
+ */
20
+ const BASE_PEERS = [
21
+ ['@angular/cdk', '>=22.0.0'],
22
+ ['lucide', '>=1.0.0'],
23
+ ];
15
24
  /** Extra peers contributed by the `dateAdapter` choice. */
16
25
  const DATE_ADAPTER_PEERS = {
17
26
  none: [],
@@ -121,11 +130,16 @@ function printNextSteps(options, context) {
121
130
  const adapter = options.dateAdapter ?? 'none';
122
131
  const density = options.density ?? 'none';
123
132
  const theme = options.theme ?? 'none';
133
+ // `ngwr/icon` exports only WrIcon / provideWrIcons / svgIcon — there are no
134
+ // bare icon exports, so the old `{ plus, trash }` import did not compile.
135
+ // Icons come from an adapter (lucide / feather) or from svgIcon().
124
136
  const imports = [
125
137
  "import { provideWrOverlay } from 'ngwr/overlay';",
126
- "import { provideWrIcons, plus, trash } from 'ngwr/icon';",
138
+ "import { provideWrIcons } from 'ngwr/icon';",
139
+ "import { lucideIcons } from 'ngwr/icon/adapters/lucide';",
140
+ "import { Plus, Trash2 } from 'lucide';",
127
141
  ];
128
- const providers = ['provideWrOverlay()', 'provideWrIcons([plus, trash])'];
142
+ const providers = ['provideWrOverlay()', 'provideWrIcons(lucideIcons({ plus: Plus, trash: Trash2 }))'];
129
143
  const adapterCall = DATE_ADAPTER_PROVIDER[adapter];
130
144
  if (adapterCall) {
131
145
  imports.push("import { provideWrDateAdapter } from 'ngwr/date-adapter';");
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -84,6 +84,8 @@
84
84
  "WrDateFnsAdapter": "ngwr/date-adapter-fns",
85
85
  "WrLuxonAdapter": "ngwr/date-adapter-luxon",
86
86
  "WrDatePicker": "ngwr/date-picker",
87
+ "WrDateRangePicker": "ngwr/date-picker",
88
+ "WrDateRange": "ngwr/date-picker",
87
89
  "WrDecryptText": "ngwr/decrypt-text",
88
90
  "WrDecryptTextAnimateOn": "ngwr/decrypt-text",
89
91
  "WrDecryptTextClickMode": "ngwr/decrypt-text",
@@ -113,10 +115,13 @@
113
115
  "WrSortableReorderEvent": "ngwr/drag-drop",
114
116
  "WrDragHandle": "ngwr/drag-drop",
115
117
  "WrDrawer": "ngwr/drawer",
118
+ "WrDrawerManager": "ngwr/drawer",
119
+ "WrDrawerRef": "ngwr/drawer",
116
120
  "WrDrawerTitle": "ngwr/drawer",
117
121
  "WrDrawerContent": "ngwr/drawer",
118
122
  "WrDrawerFooter": "ngwr/drawer",
119
123
  "WrDrawerClose": "ngwr/drawer",
124
+ "WrDrawerOptions": "ngwr/drawer",
120
125
  "WrDrawerPosition": "ngwr/drawer",
121
126
  "WrDropdown": "ngwr/dropdown",
122
127
  "WrDropdownMenu": "ngwr/dropdown",
@@ -153,6 +158,7 @@
153
158
  "WrI18nParams": "ngwr/i18n",
154
159
  "WrI18nMissingHandler": "ngwr/i18n",
155
160
  "WrI18nLoader": "ngwr/i18n",
161
+ "WrI18nBaseCatalogs": "ngwr/i18n",
156
162
  "WrI18nStaticLoader": "ngwr/i18n",
157
163
  "WrI18nStaticCatalogs": "ngwr/i18n",
158
164
  "WrI18nStaticScopedCatalogs": "ngwr/i18n",
@@ -211,6 +217,7 @@
211
217
  "WrMetaTwitter": "ngwr/meta",
212
218
  "WrMeterGroup": "ngwr/meter-group",
213
219
  "WrMeterSegment": "ngwr/meter-group",
220
+ "WrOutsideClick": "ngwr/overlay",
214
221
  "WrOverlayContainer": "ngwr/overlay",
215
222
  "WrPageHeader": "ngwr/page-header",
216
223
  "WrPagination": "ngwr/pagination",
@@ -270,6 +270,10 @@
270
270
  --wr-option-padding-y: 0.4375rem;
271
271
  --wr-option-padding-x: 0.625rem;
272
272
  --wr-option-gap: 0.1875rem;
273
+ // Space between an option's own bits — an icon or checkbox and its label.
274
+ // `--wr-option-gap` above is the panel's row rhythm, a different axis; without
275
+ // this one, a projected `<wr-icon>` sat flush against the text.
276
+ --wr-option-inline-gap: 0.5rem;
273
277
 
274
278
  display: flex;
275
279
  flex-direction: column;
@@ -292,6 +296,7 @@
292
296
  --wr-option-padding-y: 0.3125rem;
293
297
  --wr-option-padding-x: 0.5rem;
294
298
  --wr-option-gap: 0.125rem;
299
+ --wr-option-inline-gap: 0.375rem;
295
300
  }
296
301
 
297
302
  &--lg {
@@ -300,6 +305,7 @@
300
305
  --wr-option-padding-y: 0.5rem;
301
306
  --wr-option-padding-x: 0.75rem;
302
307
  --wr-option-gap: 0.25rem;
308
+ --wr-option-inline-gap: 0.625rem;
303
309
  }
304
310
 
305
311
  &__loading,
@@ -314,6 +320,7 @@
314
320
  .wr-option {
315
321
  display: flex;
316
322
  align-items: center;
323
+ gap: var(--wr-option-inline-gap, 0.5rem);
317
324
  padding: var(--wr-option-padding-y) var(--wr-option-padding-x);
318
325
  border-radius: var(--wr-border-radius-sm);
319
326
  color: var(--wr-color-on-surface);
@@ -399,6 +406,12 @@
399
406
  text-transform: uppercase;
400
407
  }
401
408
 
409
+ // A group needs a visible seam above it, or its label reads as one more dim
410
+ // option in the list. This only fired between two groups, so the common shape
411
+ // — loose options and then a group — got no divider at all. Match a preceding
412
+ // option too; deliberately not `* + &`, which would also draw a line under the
413
+ // search field, where the field's own border already does the job.
414
+ .wr-option + &,
402
415
  + .wr-option-group {
403
416
  border-top: 1px solid var(--wr-color-outline);
404
417
  margin-top: 0.25rem;
@@ -19,7 +19,13 @@
19
19
 
20
20
  &__pane {
21
21
  flex-grow: 0;
22
- flex-shrink: 0;
22
+ // Shrinkable on purpose. The two panes are sized in percentages that add up
23
+ // to 100, and the 4px divider sits between them — with `flex-shrink: 0` the
24
+ // row came to 100% + 4px and both panes hung over the container's edge.
25
+ // Shrinking splits that 4px between them and keeps the ratio the drag set.
26
+ // Safe to shrink: `min-width: 0` plus `overflow: auto` means content never
27
+ // props a pane open.
28
+ flex-shrink: 1;
23
29
  min-width: 0;
24
30
  min-height: 0;
25
31
  overflow: auto;