@joanroucoux/cairn-ui 0.8.2 → 0.9.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 (124) hide show
  1. package/CHANGELOG.md +114 -0
  2. package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs +57 -53
  3. package/fesm2022/joanroucoux-cairn-ui-action-bar.mjs.map +1 -1
  4. package/fesm2022/joanroucoux-cairn-ui-alert.mjs +155 -47
  5. package/fesm2022/joanroucoux-cairn-ui-alert.mjs.map +1 -1
  6. package/fesm2022/joanroucoux-cairn-ui-amount.mjs +220 -110
  7. package/fesm2022/joanroucoux-cairn-ui-amount.mjs.map +1 -1
  8. package/fesm2022/joanroucoux-cairn-ui-async.mjs +392 -216
  9. package/fesm2022/joanroucoux-cairn-ui-async.mjs.map +1 -1
  10. package/fesm2022/joanroucoux-cairn-ui-avatar.mjs +145 -68
  11. package/fesm2022/joanroucoux-cairn-ui-avatar.mjs.map +1 -1
  12. package/fesm2022/joanroucoux-cairn-ui-back-link.mjs +87 -47
  13. package/fesm2022/joanroucoux-cairn-ui-back-link.mjs.map +1 -1
  14. package/fesm2022/joanroucoux-cairn-ui-badge.mjs +83 -43
  15. package/fesm2022/joanroucoux-cairn-ui-badge.mjs.map +1 -1
  16. package/fesm2022/joanroucoux-cairn-ui-button.mjs +184 -104
  17. package/fesm2022/joanroucoux-cairn-ui-button.mjs.map +1 -1
  18. package/fesm2022/joanroucoux-cairn-ui-card.mjs +232 -137
  19. package/fesm2022/joanroucoux-cairn-ui-card.mjs.map +1 -1
  20. package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs +298 -102
  21. package/fesm2022/joanroucoux-cairn-ui-choice-chips.mjs.map +1 -1
  22. package/fesm2022/joanroucoux-cairn-ui-control.mjs +4 -17
  23. package/fesm2022/joanroucoux-cairn-ui-control.mjs.map +1 -1
  24. package/fesm2022/joanroucoux-cairn-ui-delta.mjs +150 -83
  25. package/fesm2022/joanroucoux-cairn-ui-delta.mjs.map +1 -1
  26. package/fesm2022/joanroucoux-cairn-ui-dialog.mjs +508 -471
  27. package/fesm2022/joanroucoux-cairn-ui-dialog.mjs.map +1 -1
  28. package/fesm2022/joanroucoux-cairn-ui-donut.mjs +255 -157
  29. package/fesm2022/joanroucoux-cairn-ui-donut.mjs.map +1 -1
  30. package/fesm2022/joanroucoux-cairn-ui-drawer.mjs +303 -0
  31. package/fesm2022/joanroucoux-cairn-ui-drawer.mjs.map +1 -0
  32. package/fesm2022/joanroucoux-cairn-ui-empty.mjs +76 -35
  33. package/fesm2022/joanroucoux-cairn-ui-empty.mjs.map +1 -1
  34. package/fesm2022/joanroucoux-cairn-ui-external-link.mjs +40 -31
  35. package/fesm2022/joanroucoux-cairn-ui-external-link.mjs.map +1 -1
  36. package/fesm2022/joanroucoux-cairn-ui-fact.mjs +188 -79
  37. package/fesm2022/joanroucoux-cairn-ui-fact.mjs.map +1 -1
  38. package/fesm2022/joanroucoux-cairn-ui-field.mjs +309 -173
  39. package/fesm2022/joanroucoux-cairn-ui-field.mjs.map +1 -1
  40. package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs +165 -87
  41. package/fesm2022/joanroucoux-cairn-ui-filter-chips.mjs.map +1 -1
  42. package/fesm2022/joanroucoux-cairn-ui-group-header.mjs +269 -0
  43. package/fesm2022/joanroucoux-cairn-ui-group-header.mjs.map +1 -0
  44. package/fesm2022/joanroucoux-cairn-ui-input.mjs +205 -85
  45. package/fesm2022/joanroucoux-cairn-ui-input.mjs.map +1 -1
  46. package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs +838 -512
  47. package/fesm2022/joanroucoux-cairn-ui-line-chart.mjs.map +1 -1
  48. package/fesm2022/joanroucoux-cairn-ui-menu.mjs +401 -225
  49. package/fesm2022/joanroucoux-cairn-ui-menu.mjs.map +1 -1
  50. package/fesm2022/joanroucoux-cairn-ui-meter.mjs +143 -57
  51. package/fesm2022/joanroucoux-cairn-ui-meter.mjs.map +1 -1
  52. package/fesm2022/joanroucoux-cairn-ui-motion.mjs +367 -399
  53. package/fesm2022/joanroucoux-cairn-ui-motion.mjs.map +1 -1
  54. package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs +73 -44
  55. package/fesm2022/joanroucoux-cairn-ui-nav-item.mjs.map +1 -1
  56. package/fesm2022/joanroucoux-cairn-ui-result-group.mjs +191 -0
  57. package/fesm2022/joanroucoux-cairn-ui-result-group.mjs.map +1 -0
  58. package/fesm2022/joanroucoux-cairn-ui-row.mjs +408 -146
  59. package/fesm2022/joanroucoux-cairn-ui-row.mjs.map +1 -1
  60. package/fesm2022/joanroucoux-cairn-ui-segmented.mjs +183 -81
  61. package/fesm2022/joanroucoux-cairn-ui-segmented.mjs.map +1 -1
  62. package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs +270 -0
  63. package/fesm2022/joanroucoux-cairn-ui-select-pill.mjs.map +1 -0
  64. package/fesm2022/joanroucoux-cairn-ui-select.mjs +121 -67
  65. package/fesm2022/joanroucoux-cairn-ui-select.mjs.map +1 -1
  66. package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs +129 -51
  67. package/fesm2022/joanroucoux-cairn-ui-skeleton.mjs.map +1 -1
  68. package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs +80 -39
  69. package/fesm2022/joanroucoux-cairn-ui-stale-link.mjs.map +1 -1
  70. package/fesm2022/joanroucoux-cairn-ui-stat.mjs +85 -55
  71. package/fesm2022/joanroucoux-cairn-ui-stat.mjs.map +1 -1
  72. package/fesm2022/joanroucoux-cairn-ui-switch.mjs +48 -35
  73. package/fesm2022/joanroucoux-cairn-ui-switch.mjs.map +1 -1
  74. package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs +113 -69
  75. package/fesm2022/joanroucoux-cairn-ui-tab-bar.mjs.map +1 -1
  76. package/fesm2022/joanroucoux-cairn-ui-table.mjs +1036 -310
  77. package/fesm2022/joanroucoux-cairn-ui-table.mjs.map +1 -1
  78. package/fesm2022/joanroucoux-cairn-ui-toast.mjs +240 -127
  79. package/fesm2022/joanroucoux-cairn-ui-toast.mjs.map +1 -1
  80. package/fesm2022/joanroucoux-cairn-ui.mjs +0 -4
  81. package/package.json +17 -1
  82. package/styles/motion.css +1 -13
  83. package/styles/tokens.css +35 -64
  84. package/types/joanroucoux-cairn-ui-action-bar.d.ts +9 -14
  85. package/types/joanroucoux-cairn-ui-alert.d.ts +29 -15
  86. package/types/joanroucoux-cairn-ui-amount.d.ts +64 -32
  87. package/types/joanroucoux-cairn-ui-async.d.ts +85 -38
  88. package/types/joanroucoux-cairn-ui-avatar.d.ts +34 -22
  89. package/types/joanroucoux-cairn-ui-back-link.d.ts +20 -15
  90. package/types/joanroucoux-cairn-ui-badge.d.ts +22 -14
  91. package/types/joanroucoux-cairn-ui-button.d.ts +36 -18
  92. package/types/joanroucoux-cairn-ui-card.d.ts +48 -23
  93. package/types/joanroucoux-cairn-ui-choice-chips.d.ts +91 -35
  94. package/types/joanroucoux-cairn-ui-control.d.ts +9 -18
  95. package/types/joanroucoux-cairn-ui-delta.d.ts +46 -24
  96. package/types/joanroucoux-cairn-ui-dialog.d.ts +124 -57
  97. package/types/joanroucoux-cairn-ui-donut.d.ts +83 -46
  98. package/types/joanroucoux-cairn-ui-drawer.d.ts +73 -0
  99. package/types/joanroucoux-cairn-ui-empty.d.ts +20 -13
  100. package/types/joanroucoux-cairn-ui-external-link.d.ts +6 -10
  101. package/types/joanroucoux-cairn-ui-fact.d.ts +49 -25
  102. package/types/joanroucoux-cairn-ui-field.d.ts +72 -49
  103. package/types/joanroucoux-cairn-ui-filter-chips.d.ts +35 -20
  104. package/types/joanroucoux-cairn-ui-group-header.d.ts +58 -0
  105. package/types/joanroucoux-cairn-ui-input.d.ts +59 -37
  106. package/types/joanroucoux-cairn-ui-line-chart.d.ts +199 -89
  107. package/types/joanroucoux-cairn-ui-menu.d.ts +81 -44
  108. package/types/joanroucoux-cairn-ui-meter.d.ts +44 -22
  109. package/types/joanroucoux-cairn-ui-motion.d.ts +61 -75
  110. package/types/joanroucoux-cairn-ui-nav-item.d.ts +15 -13
  111. package/types/joanroucoux-cairn-ui-result-group.d.ts +52 -0
  112. package/types/joanroucoux-cairn-ui-row.d.ts +92 -37
  113. package/types/joanroucoux-cairn-ui-segmented.d.ts +51 -27
  114. package/types/joanroucoux-cairn-ui-select-pill.d.ts +59 -0
  115. package/types/joanroucoux-cairn-ui-select.d.ts +28 -18
  116. package/types/joanroucoux-cairn-ui-skeleton.d.ts +35 -18
  117. package/types/joanroucoux-cairn-ui-stale-link.d.ts +23 -16
  118. package/types/joanroucoux-cairn-ui-stat.d.ts +26 -21
  119. package/types/joanroucoux-cairn-ui-switch.d.ts +7 -11
  120. package/types/joanroucoux-cairn-ui-tab-bar.d.ts +20 -17
  121. package/types/joanroucoux-cairn-ui-table.d.ts +251 -89
  122. package/types/joanroucoux-cairn-ui-toast.d.ts +46 -36
  123. package/types/joanroucoux-cairn-ui.d.ts +1 -2
  124. package/fesm2022/joanroucoux-cairn-ui.mjs.map +0 -1
@@ -1,91 +1,179 @@
1
- import * as i0 from '@angular/core';
2
- import { input, model, booleanAttribute, output, inject, ElementRef, viewChildren, computed, forwardRef, Component } from '@angular/core';
3
- import { UI_CONTROL } from '@joanroucoux/cairn-ui/control';
4
- import { CONTROL_SURFACE_CLASSES } from '@joanroucoux/cairn-ui/input';
5
-
6
- const CHIP_CLASSES = 'h-10 px-3.5 pointer-fine:h-8 pointer-fine:px-3 rounded-pill text-label font-medium cursor-pointer transition-transform duration-(--duration-press) ease-out active:scale-(--press-scale) disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)';
7
- const SELECTED_CLASSES = 'bg-(--primary) text-(--primary-foreground)';
8
- const UNSELECTED_CLASSES = 'text-(--foreground) shadow-[inset_0_0_0_1px_var(--border)]';
1
+ import * as i0 from "@angular/core";
2
+ import { Component, ElementRef, booleanAttribute, computed, forwardRef, inject, input, model, output, viewChildren } from "@angular/core";
3
+ import { UI_CONTROL } from "@joanroucoux/cairn-ui/control";
4
+ import { CONTROL_SURFACE_CLASSES } from "@joanroucoux/cairn-ui/input";
5
+ const CHIP_CLASSES = "h-10 px-3.5 pointer-fine:h-8 pointer-fine:px-3 rounded-pill text-label font-medium cursor-pointer transition-transform duration-(--duration-press) ease-out active:scale-(--press-scale) disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)";
6
+ const SELECTED_CLASSES = "bg-(--primary) text-(--primary-foreground)";
7
+ const UNSELECTED_CLASSES = "text-(--foreground) shadow-[inset_0_0_0_1px_var(--border)]";
9
8
  const nextId = (() => {
10
- let count = 0;
11
- return () => `ui-choice-chips-${++count}`;
9
+ let count = 0;
10
+ return () => `ui-choice-chips-${++count}`;
12
11
  })();
13
- /**
14
- * Exclusive choice among a handful of named options, shown as wrapping pills: an account envelope,
15
- * a category, a frequency. Binds to Signal Forms with `[formField]`.
16
- *
17
- * @example
18
- * <ui-choice-chips label="Envelope" [options]="envelopes" [(value)]="envelope" />
19
- *
20
- * @example
21
- * <ui-choice-chips label="Envelope" [options]="envelopes" [formField]="form.envelope" />
22
- */
23
- class UiChoiceChips {
24
- options = input.required(/* @ts-ignore */
25
- ...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
26
- value = model.required(/* @ts-ignore */
27
- ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
28
- label = input(/* @ts-ignore */
29
- ...(ngDevMode ? [undefined, { debugName: "label" }] : /* istanbul ignore next */ []));
30
- ariaLabel = input(/* @ts-ignore */
31
- ...(ngDevMode ? [undefined, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
32
- ariaLabelledby = input(/* @ts-ignore */
33
- ...(ngDevMode ? [undefined, { debugName: "ariaLabelledby" }] : /* istanbul ignore next */ []));
34
- surface = input('background', /* @ts-ignore */
35
- ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
36
- disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
37
- errors = input([], /* @ts-ignore */
38
- ...(ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []));
39
- invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
40
- required = input(false, { ...(ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
41
- touched = input(false, /* @ts-ignore */
42
- ...(ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []));
43
- touch = output();
44
- labelId = nextId();
45
- #host = inject(ElementRef);
46
- radios = viewChildren('radio', /* @ts-ignore */
47
- ...(ngDevMode ? [{ debugName: "radios" }] : /* istanbul ignore next */ []));
48
- labelledBy = computed(() => this.ariaLabelledby() ?? (this.label() ? this.labelId : null), /* @ts-ignore */
49
- ...(ngDevMode ? [{ debugName: "labelledBy" }] : /* istanbul ignore next */ []));
50
- chipClasses(optionValue) {
51
- const state = optionValue === this.value()
52
- ? SELECTED_CLASSES
53
- : `${CONTROL_SURFACE_CLASSES[this.surface()]} ${UNSELECTED_CLASSES}`;
54
- return `${CHIP_CLASSES} ${state}`;
55
- }
56
- tabIndexFor(optionValue) {
57
- const opts = this.options();
58
- const tabStopValue = opts.some((option) => option.value === this.value()) ? this.value() : opts[0]?.value;
59
- return optionValue === tabStopValue ? 0 : -1;
60
- }
61
- select(optionValue) {
62
- this.value.set(optionValue);
63
- }
64
- onFocusOut(event) {
65
- if (!this.#host.nativeElement.contains(event.relatedTarget)) {
66
- this.touch.emit();
67
- }
68
- }
69
- onKeydown(event, index) {
70
- const opts = this.options();
71
- const target = {
72
- ArrowRight: index + 1,
73
- ArrowDown: index + 1,
74
- ArrowLeft: index - 1,
75
- ArrowUp: index - 1,
76
- Home: 0,
77
- End: opts.length - 1,
78
- }[event.key];
79
- if (target === undefined) {
80
- return;
81
- }
82
- event.preventDefault();
83
- const nextIndex = ((target % opts.length) + opts.length) % opts.length;
84
- this.value.set(opts[nextIndex].value);
85
- this.radios()[nextIndex].nativeElement.focus();
86
- }
87
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiChoiceChips, deps: [], target: i0.ɵɵFactoryTarget.Component });
88
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: UiChoiceChips, isStandalone: true, selector: "ui-choice-chips", inputs: { options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, ariaLabelledby: { classPropertyName: "ariaLabelledby", publicName: "ariaLabelledby", isSignal: true, isRequired: false, transformFunction: null }, surface: { classPropertyName: "surface", publicName: "surface", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, errors: { classPropertyName: "errors", publicName: "errors", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touch: "touch" }, providers: [{ provide: UI_CONTROL, useExisting: forwardRef(() => UiChoiceChips) }], viewQueries: [{ propertyName: "radios", predicate: ["radio"], descendants: true, isSignal: true }], ngImport: i0, template: `
12
+ var UiChoiceChips = class UiChoiceChips {
13
+ options = input.required(...ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []);
14
+ value = model.required(...ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []);
15
+ label = input(...ngDevMode ? [void 0, { debugName: "label" }] : /* istanbul ignore next */ []);
16
+ ariaLabel = input(...ngDevMode ? [void 0, { debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
17
+ ariaLabelledby = input(...ngDevMode ? [void 0, { debugName: "ariaLabelledby" }] : /* istanbul ignore next */ []);
18
+ surface = input("background", ...ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []);
19
+ disabled = input(false, {
20
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
21
+ transform: booleanAttribute
22
+ });
23
+ errors = input([], ...ngDevMode ? [{ debugName: "errors" }] : /* istanbul ignore next */ []);
24
+ invalid = input(false, {
25
+ ...ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {},
26
+ transform: booleanAttribute
27
+ });
28
+ required = input(false, {
29
+ ...ngDevMode ? { debugName: "required" } : /* istanbul ignore next */ {},
30
+ transform: booleanAttribute
31
+ });
32
+ touched = input(false, ...ngDevMode ? [{ debugName: "touched" }] : /* istanbul ignore next */ []);
33
+ touch = output();
34
+ labelId = nextId();
35
+ #host = inject(ElementRef);
36
+ radios = viewChildren("radio", ...ngDevMode ? [{ debugName: "radios" }] : /* istanbul ignore next */ []);
37
+ labelledBy = computed(() => this.ariaLabelledby() ?? (this.label() ? this.labelId : null), ...ngDevMode ? [{ debugName: "labelledBy" }] : /* istanbul ignore next */ []);
38
+ chipClasses(optionValue) {
39
+ const state = optionValue === this.value() ? SELECTED_CLASSES : `${CONTROL_SURFACE_CLASSES[this.surface()]} ${UNSELECTED_CLASSES}`;
40
+ return `${CHIP_CLASSES} ${state}`;
41
+ }
42
+ tabIndexFor(optionValue) {
43
+ const opts = this.options();
44
+ return optionValue === (opts.some((option) => option.value === this.value()) ? this.value() : opts[0]?.value) ? 0 : -1;
45
+ }
46
+ select(optionValue) {
47
+ this.value.set(optionValue);
48
+ }
49
+ onFocusOut(event) {
50
+ if (!this.#host.nativeElement.contains(event.relatedTarget)) this.touch.emit();
51
+ }
52
+ onKeydown(event, index) {
53
+ const opts = this.options();
54
+ const target = {
55
+ ArrowRight: index + 1,
56
+ ArrowDown: index + 1,
57
+ ArrowLeft: index - 1,
58
+ ArrowUp: index - 1,
59
+ Home: 0,
60
+ End: opts.length - 1
61
+ }[event.key];
62
+ if (target === void 0) return;
63
+ event.preventDefault();
64
+ const nextIndex = (target % opts.length + opts.length) % opts.length;
65
+ this.value.set(opts[nextIndex].value);
66
+ this.radios()[nextIndex].nativeElement.focus();
67
+ }
68
+ static ɵfac = i0.ɵɵngDeclareFactory({
69
+ minVersion: "12.0.0",
70
+ version: "22.2.0",
71
+ ngImport: i0,
72
+ type: UiChoiceChips,
73
+ deps: [],
74
+ target: i0.ɵɵFactoryTarget.Component
75
+ });
76
+ static ɵcmp = i0.ɵɵngDeclareComponent({
77
+ minVersion: "17.0.0",
78
+ version: "22.2.0",
79
+ type: UiChoiceChips,
80
+ isStandalone: true,
81
+ selector: "ui-choice-chips",
82
+ inputs: {
83
+ options: {
84
+ classPropertyName: "options",
85
+ publicName: "options",
86
+ isSignal: true,
87
+ isRequired: true,
88
+ transformFunction: null
89
+ },
90
+ value: {
91
+ classPropertyName: "value",
92
+ publicName: "value",
93
+ isSignal: true,
94
+ isRequired: true,
95
+ transformFunction: null
96
+ },
97
+ label: {
98
+ classPropertyName: "label",
99
+ publicName: "label",
100
+ isSignal: true,
101
+ isRequired: false,
102
+ transformFunction: null
103
+ },
104
+ ariaLabel: {
105
+ classPropertyName: "ariaLabel",
106
+ publicName: "ariaLabel",
107
+ isSignal: true,
108
+ isRequired: false,
109
+ transformFunction: null
110
+ },
111
+ ariaLabelledby: {
112
+ classPropertyName: "ariaLabelledby",
113
+ publicName: "ariaLabelledby",
114
+ isSignal: true,
115
+ isRequired: false,
116
+ transformFunction: null
117
+ },
118
+ surface: {
119
+ classPropertyName: "surface",
120
+ publicName: "surface",
121
+ isSignal: true,
122
+ isRequired: false,
123
+ transformFunction: null
124
+ },
125
+ disabled: {
126
+ classPropertyName: "disabled",
127
+ publicName: "disabled",
128
+ isSignal: true,
129
+ isRequired: false,
130
+ transformFunction: null
131
+ },
132
+ errors: {
133
+ classPropertyName: "errors",
134
+ publicName: "errors",
135
+ isSignal: true,
136
+ isRequired: false,
137
+ transformFunction: null
138
+ },
139
+ invalid: {
140
+ classPropertyName: "invalid",
141
+ publicName: "invalid",
142
+ isSignal: true,
143
+ isRequired: false,
144
+ transformFunction: null
145
+ },
146
+ required: {
147
+ classPropertyName: "required",
148
+ publicName: "required",
149
+ isSignal: true,
150
+ isRequired: false,
151
+ transformFunction: null
152
+ },
153
+ touched: {
154
+ classPropertyName: "touched",
155
+ publicName: "touched",
156
+ isSignal: true,
157
+ isRequired: false,
158
+ transformFunction: null
159
+ }
160
+ },
161
+ outputs: {
162
+ value: "valueChange",
163
+ touch: "touch"
164
+ },
165
+ providers: [{
166
+ provide: UI_CONTROL,
167
+ useExisting: forwardRef(() => UiChoiceChips)
168
+ }],
169
+ viewQueries: [{
170
+ propertyName: "radios",
171
+ predicate: ["radio"],
172
+ descendants: true,
173
+ isSignal: true
174
+ }],
175
+ ngImport: i0,
176
+ template: `
89
177
  <div
90
178
  class="flex flex-col gap-1.5"
91
179
  role="radiogroup"
@@ -119,13 +207,20 @@ class UiChoiceChips {
119
207
  }
120
208
  </div>
121
209
  </div>
122
- `, isInline: true });
123
- }
124
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: UiChoiceChips, decorators: [{
125
- type: Component,
126
- args: [{
127
- selector: 'ui-choice-chips',
128
- template: `
210
+ `,
211
+ isInline: true
212
+ });
213
+ };
214
+ i0.ɵɵngDeclareClassMetadata({
215
+ minVersion: "12.0.0",
216
+ version: "22.2.0",
217
+ ngImport: i0,
218
+ type: UiChoiceChips,
219
+ decorators: [{
220
+ type: Component,
221
+ args: [{
222
+ selector: "ui-choice-chips",
223
+ template: `
129
224
  <div
130
225
  class="flex flex-col gap-1.5"
131
226
  role="radiogroup"
@@ -160,13 +255,114 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImpor
160
255
  </div>
161
256
  </div>
162
257
  `,
163
- providers: [{ provide: UI_CONTROL, useExisting: forwardRef(() => UiChoiceChips) }],
164
- }]
165
- }], propDecorators: { options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: true }] }, { type: i0.Output, args: ["valueChange"] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], ariaLabelledby: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabelledby", required: false }] }], surface: [{ type: i0.Input, args: [{ isSignal: true, alias: "surface", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], errors: [{ type: i0.Input, args: [{ isSignal: true, alias: "errors", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }], touch: [{ type: i0.Output, args: ["touch"] }], radios: [{ type: i0.ViewChildren, args: ['radio', { isSignal: true }] }] } });
166
-
167
- /**
168
- * Generated bundle index. Do not edit.
169
- */
170
-
258
+ providers: [{
259
+ provide: UI_CONTROL,
260
+ useExisting: forwardRef(() => UiChoiceChips)
261
+ }]
262
+ }]
263
+ }],
264
+ propDecorators: {
265
+ options: [{
266
+ type: i0.Input,
267
+ args: [{
268
+ isSignal: true,
269
+ alias: "options",
270
+ required: true
271
+ }]
272
+ }],
273
+ value: [{
274
+ type: i0.Input,
275
+ args: [{
276
+ isSignal: true,
277
+ alias: "value",
278
+ required: true
279
+ }]
280
+ }, {
281
+ type: i0.Output,
282
+ args: ["valueChange"]
283
+ }],
284
+ label: [{
285
+ type: i0.Input,
286
+ args: [{
287
+ isSignal: true,
288
+ alias: "label",
289
+ required: false
290
+ }]
291
+ }],
292
+ ariaLabel: [{
293
+ type: i0.Input,
294
+ args: [{
295
+ isSignal: true,
296
+ alias: "ariaLabel",
297
+ required: false
298
+ }]
299
+ }],
300
+ ariaLabelledby: [{
301
+ type: i0.Input,
302
+ args: [{
303
+ isSignal: true,
304
+ alias: "ariaLabelledby",
305
+ required: false
306
+ }]
307
+ }],
308
+ surface: [{
309
+ type: i0.Input,
310
+ args: [{
311
+ isSignal: true,
312
+ alias: "surface",
313
+ required: false
314
+ }]
315
+ }],
316
+ disabled: [{
317
+ type: i0.Input,
318
+ args: [{
319
+ isSignal: true,
320
+ alias: "disabled",
321
+ required: false
322
+ }]
323
+ }],
324
+ errors: [{
325
+ type: i0.Input,
326
+ args: [{
327
+ isSignal: true,
328
+ alias: "errors",
329
+ required: false
330
+ }]
331
+ }],
332
+ invalid: [{
333
+ type: i0.Input,
334
+ args: [{
335
+ isSignal: true,
336
+ alias: "invalid",
337
+ required: false
338
+ }]
339
+ }],
340
+ required: [{
341
+ type: i0.Input,
342
+ args: [{
343
+ isSignal: true,
344
+ alias: "required",
345
+ required: false
346
+ }]
347
+ }],
348
+ touched: [{
349
+ type: i0.Input,
350
+ args: [{
351
+ isSignal: true,
352
+ alias: "touched",
353
+ required: false
354
+ }]
355
+ }],
356
+ touch: [{
357
+ type: i0.Output,
358
+ args: ["touch"]
359
+ }],
360
+ radios: [{
361
+ type: i0.ViewChildren,
362
+ args: ["radio", { isSignal: true }]
363
+ }]
364
+ }
365
+ });
171
366
  export { UiChoiceChips };
172
- //# sourceMappingURL=joanroucoux-cairn-ui-choice-chips.mjs.map
367
+
368
+ //# sourceMappingURL=joanroucoux-cairn-ui-choice-chips.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-choice-chips.mjs","sources":["../../../projects/ui/choice-chips/choice-chips.ts","../../../projects/ui/choice-chips/joanroucoux-cairn-ui-choice-chips.ts"],"sourcesContent":["import {\n Component,\n ElementRef,\n booleanAttribute,\n computed,\n forwardRef,\n inject,\n input,\n model,\n output,\n viewChildren,\n} from '@angular/core';\n\nimport { UI_CONTROL, type UiControl, type UiControlError } from '@joanroucoux/cairn-ui/control';\nimport { CONTROL_SURFACE_CLASSES, type ControlSurface } from '@joanroucoux/cairn-ui/input';\n\nexport type ChoiceChipOption = {\n value: string;\n label: string;\n};\n\nconst CHIP_CLASSES =\n 'h-10 px-3.5 pointer-fine:h-8 pointer-fine:px-3 rounded-pill text-label font-medium cursor-pointer transition-transform duration-(--duration-press) ease-out active:scale-(--press-scale) disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)';\n\nconst SELECTED_CLASSES = 'bg-(--primary) text-(--primary-foreground)';\n\nconst UNSELECTED_CLASSES = 'text-(--foreground) shadow-[inset_0_0_0_1px_var(--border)]';\n\nconst nextId = (() => {\n let count = 0;\n\n return (): string => `ui-choice-chips-${++count}`;\n})();\n\n/**\n * Exclusive choice among a handful of named options, shown as wrapping pills: an account envelope,\n * a category, a frequency. Binds to Signal Forms with `[formField]`.\n *\n * @example\n * <ui-choice-chips label=\"Envelope\" [options]=\"envelopes\" [(value)]=\"envelope\" />\n *\n * @example\n * <ui-choice-chips label=\"Envelope\" [options]=\"envelopes\" [formField]=\"form.envelope\" />\n */\n@Component({\n selector: 'ui-choice-chips',\n template: `\n <div\n class=\"flex flex-col gap-1.5\"\n role=\"radiogroup\"\n [attr.aria-invalid]=\"invalid() || null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-required]=\"required() || null\"\n (focusout)=\"onFocusOut($event)\"\n >\n @if (label()) {\n <span class=\"text-label leading-[17px] font-medium text-(--muted-foreground)\" [id]=\"labelId\">{{\n label()\n }}</span>\n }\n\n <div class=\"flex flex-wrap gap-1.5\">\n @for (option of options(); track option.value; let index = $index) {\n <button\n #radio\n role=\"radio\"\n type=\"button\"\n [attr.aria-checked]=\"option.value === value()\"\n [attr.tabindex]=\"tabIndexFor(option.value)\"\n [class]=\"chipClasses(option.value)\"\n [disabled]=\"disabled()\"\n (click)=\"select(option.value)\"\n (keydown)=\"onKeydown($event, index)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n `,\n providers: [{ provide: UI_CONTROL, useExisting: forwardRef(() => UiChoiceChips) }],\n})\nexport class UiChoiceChips implements UiControl {\n readonly options = input.required<ChoiceChipOption[]>();\n readonly value = model.required<string>();\n readonly label = input<string>();\n readonly ariaLabel = input<string>();\n readonly ariaLabelledby = input<string>();\n readonly surface = input<ControlSurface>('background');\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly errors = input<readonly UiControlError[]>([]);\n readonly invalid = input(false, { transform: booleanAttribute });\n readonly required = input(false, { transform: booleanAttribute });\n readonly touched = input(false);\n readonly touch = output<void>();\n\n protected readonly labelId = nextId();\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef);\n protected readonly radios = viewChildren<ElementRef<HTMLButtonElement>>('radio');\n\n protected readonly labelledBy = computed(() => this.ariaLabelledby() ?? (this.label() ? this.labelId : null));\n\n protected chipClasses(optionValue: string): string {\n const state =\n optionValue === this.value()\n ? SELECTED_CLASSES\n : `${CONTROL_SURFACE_CLASSES[this.surface()]} ${UNSELECTED_CLASSES}`;\n\n return `${CHIP_CLASSES} ${state}`;\n }\n\n protected tabIndexFor(optionValue: string): number {\n const opts = this.options();\n const tabStopValue = opts.some((option) => option.value === this.value()) ? this.value() : opts[0]?.value;\n\n return optionValue === tabStopValue ? 0 : -1;\n }\n\n protected select(optionValue: string): void {\n this.value.set(optionValue);\n }\n\n protected onFocusOut(event: FocusEvent): void {\n if (!this.#host.nativeElement.contains(event.relatedTarget as Node | null)) {\n this.touch.emit();\n }\n }\n\n protected onKeydown(event: KeyboardEvent, index: number): void {\n const opts = this.options();\n const target = {\n ArrowRight: index + 1,\n ArrowDown: index + 1,\n ArrowLeft: index - 1,\n ArrowUp: index - 1,\n Home: 0,\n End: opts.length - 1,\n }[event.key];\n\n if (target === undefined) {\n return;\n }\n event.preventDefault();\n\n const nextIndex = ((target % opts.length) + opts.length) % opts.length;\n\n this.value.set(opts[nextIndex]!.value);\n this.radios()[nextIndex]!.nativeElement.focus();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-choice-chips.mjs","names":[],"sources":["../../../projects/ui/choice-chips/choice-chips.ts"],"sourcesContent":["import {\n Component,\n ElementRef,\n booleanAttribute,\n computed,\n forwardRef,\n inject,\n input,\n model,\n output,\n viewChildren,\n} from '@angular/core';\n\nimport { UI_CONTROL, type UiControl, type UiControlError } from '@joanroucoux/cairn-ui/control';\nimport { CONTROL_SURFACE_CLASSES, type ControlSurface } from '@joanroucoux/cairn-ui/input';\n\nexport type ChoiceChipOption = {\n value: string;\n label: string;\n};\n\nconst CHIP_CLASSES =\n 'h-10 px-3.5 pointer-fine:h-8 pointer-fine:px-3 rounded-pill text-label font-medium cursor-pointer transition-transform duration-(--duration-press) ease-out active:scale-(--press-scale) disabled:cursor-not-allowed disabled:opacity-50 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--ring)';\n\nconst SELECTED_CLASSES = 'bg-(--primary) text-(--primary-foreground)';\n\nconst UNSELECTED_CLASSES = 'text-(--foreground) shadow-[inset_0_0_0_1px_var(--border)]';\n\nconst nextId = (() => {\n let count = 0;\n\n return (): string => `ui-choice-chips-${++count}`;\n})();\n\n/**\n * Exclusive choice among a handful of named options, shown as wrapping pills. Binds to Signal Forms\n * with `[formField]`.\n *\n * @example\n * <ui-choice-chips label=\"Envelope\" [options]=\"envelopes\" [(value)]=\"envelope\" />\n *\n * @example\n * <ui-choice-chips label=\"Envelope\" [options]=\"envelopes\" [formField]=\"form.envelope\" />\n */\n@Component({\n selector: 'ui-choice-chips',\n template: `\n <div\n class=\"flex flex-col gap-1.5\"\n role=\"radiogroup\"\n [attr.aria-invalid]=\"invalid() || null\"\n [attr.aria-label]=\"ariaLabel() ?? null\"\n [attr.aria-labelledby]=\"labelledBy()\"\n [attr.aria-required]=\"required() || null\"\n (focusout)=\"onFocusOut($event)\"\n >\n @if (label()) {\n <span class=\"text-label leading-[17px] font-medium text-(--muted-foreground)\" [id]=\"labelId\">{{\n label()\n }}</span>\n }\n\n <div class=\"flex flex-wrap gap-1.5\">\n @for (option of options(); track option.value; let index = $index) {\n <button\n #radio\n role=\"radio\"\n type=\"button\"\n [attr.aria-checked]=\"option.value === value()\"\n [attr.tabindex]=\"tabIndexFor(option.value)\"\n [class]=\"chipClasses(option.value)\"\n [disabled]=\"disabled()\"\n (click)=\"select(option.value)\"\n (keydown)=\"onKeydown($event, index)\"\n >\n {{ option.label }}\n </button>\n }\n </div>\n </div>\n `,\n providers: [{ provide: UI_CONTROL, useExisting: forwardRef(() => UiChoiceChips) }],\n})\nexport class UiChoiceChips implements UiControl {\n readonly options = input.required<ChoiceChipOption[]>();\n readonly value = model.required<string>();\n readonly label = input<string>();\n readonly ariaLabel = input<string>();\n readonly ariaLabelledby = input<string>();\n readonly surface = input<ControlSurface>('background');\n readonly disabled = input(false, { transform: booleanAttribute });\n readonly errors = input<readonly UiControlError[]>([]);\n readonly invalid = input(false, { transform: booleanAttribute });\n readonly required = input(false, { transform: booleanAttribute });\n readonly touched = input(false);\n readonly touch = output<void>();\n\n protected readonly labelId = nextId();\n readonly #host = inject<ElementRef<HTMLElement>>(ElementRef);\n protected readonly radios = viewChildren<ElementRef<HTMLButtonElement>>('radio');\n\n protected readonly labelledBy = computed(() => this.ariaLabelledby() ?? (this.label() ? this.labelId : null));\n\n protected chipClasses(optionValue: string): string {\n const state =\n optionValue === this.value()\n ? SELECTED_CLASSES\n : `${CONTROL_SURFACE_CLASSES[this.surface()]} ${UNSELECTED_CLASSES}`;\n\n return `${CHIP_CLASSES} ${state}`;\n }\n\n protected tabIndexFor(optionValue: string): number {\n const opts = this.options();\n const tabStopValue = opts.some((option) => option.value === this.value()) ? this.value() : opts[0]?.value;\n\n return optionValue === tabStopValue ? 0 : -1;\n }\n\n protected select(optionValue: string): void {\n this.value.set(optionValue);\n }\n\n protected onFocusOut(event: FocusEvent): void {\n if (!this.#host.nativeElement.contains(event.relatedTarget as Node | null)) {\n this.touch.emit();\n }\n }\n\n protected onKeydown(event: KeyboardEvent, index: number): void {\n const opts = this.options();\n const target = {\n ArrowRight: index + 1,\n ArrowDown: index + 1,\n ArrowLeft: index - 1,\n ArrowUp: index - 1,\n Home: 0,\n End: opts.length - 1,\n }[event.key];\n\n if (target === undefined) {\n return;\n }\n event.preventDefault();\n\n const nextIndex = ((target % opts.length) + opts.length) % opts.length;\n\n this.value.set(opts[nextIndex]!.value);\n this.radios()[nextIndex]!.nativeElement.focus();\n }\n}\n"],"mappings":"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"}
@@ -1,18 +1,5 @@
1
- import { InjectionToken } from '@angular/core';
2
-
3
- /**
4
- * Resolves to the styled control projected into a field.
5
- *
6
- * Angular's `[formField]` directive fills any input named `errors` or `touched` on the directives
7
- * sitting on its host element, so a control declaring them receives its own validation state with
8
- * nothing written at the call site. This token is how the field finds whichever control was
9
- * projected into it.
10
- */
11
- const UI_CONTROL = new InjectionToken('UI_CONTROL');
12
-
13
- /**
14
- * Generated bundle index. Do not edit.
15
- */
16
-
1
+ import { InjectionToken } from "@angular/core";
2
+ const UI_CONTROL = new InjectionToken("UI_CONTROL");
17
3
  export { UI_CONTROL };
18
- //# sourceMappingURL=joanroucoux-cairn-ui-control.mjs.map
4
+
5
+ //# sourceMappingURL=joanroucoux-cairn-ui-control.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"joanroucoux-cairn-ui-control.mjs","sources":["../../../projects/ui/control/control.ts","../../../projects/ui/control/joanroucoux-cairn-ui-control.ts"],"sourcesContent":["import { InjectionToken, type Signal } from '@angular/core';\n\n/**\n * The part of a validation error this library reads. Angular's own `ValidationError` satisfies it,\n * which is how a Signal Forms error reaches a field without this package depending on\n * `@angular/forms`.\n */\nexport type UiControlError = { readonly message?: string };\n\n/** What a styled control offers the field wrapped around it. */\nexport type UiControl = {\n readonly errors: Signal<readonly UiControlError[]>;\n readonly touched: Signal<boolean>;\n};\n\n/**\n * Resolves to the styled control projected into a field.\n *\n * Angular's `[formField]` directive fills any input named `errors` or `touched` on the directives\n * sitting on its host element, so a control declaring them receives its own validation state with\n * nothing written at the call site. This token is how the field finds whichever control was\n * projected into it.\n */\nexport const UI_CONTROL = new InjectionToken<UiControl>('UI_CONTROL');\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAeA;;;;;;;AAOG;MACU,UAAU,GAAG,IAAI,cAAc,CAAY,YAAY;;ACvBpE;;AAEG;;;;"}
1
+ {"version":3,"file":"joanroucoux-cairn-ui-control.mjs","names":[],"sources":["../../../projects/ui/control/control.ts"],"sourcesContent":["import { InjectionToken, type Signal } from '@angular/core';\n\n/**\n * The part of a validation error this library reads. Angular's own `ValidationError` satisfies it.\n */\nexport type UiControlError = { readonly message?: string };\n\n/** What a styled control offers the field wrapped around it. */\nexport type UiControl = {\n readonly errors: Signal<readonly UiControlError[]>;\n readonly touched: Signal<boolean>;\n};\n\n/**\n * Resolves to the styled control projected into a field. A control provides it and declares the\n * `errors` and `touched` inputs that Angular's `[formField]` fills.\n */\nexport const UI_CONTROL = new InjectionToken<UiControl>('UI_CONTROL');\n"],"mappings":";AAiBA,MAAa,aAAa,IAAI,eAA0B,YAAY"}