@uni-design-system/uni-core 9.0.0 → 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.
- package/CHANGELOG.md +228 -0
- package/dist/cjs/index.cjs +55 -4
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/esm/index.js +55 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/types/concepts/component/component.types.d.ts +1 -1
- package/dist/types/concepts/component/component.types.d.ts.map +1 -1
- package/dist/types/concepts/theme/themes/base.theme.d.ts.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,233 @@
|
|
|
1
1
|
# @uni-design-system/uni-core
|
|
2
2
|
|
|
3
|
+
## 10.0.0
|
|
4
|
+
|
|
5
|
+
### Major Changes
|
|
6
|
+
|
|
7
|
+
- [`21b655d`](https://github.com/uni-design-system/uni/commit/21b655df0f93e2e2de6a22ccf38050b474d4e5ab) Thanks [@gaenglish](https://github.com/gaenglish)! - `uni-slider` is rebuilt on custom thumbs instead of `<input type="range">`,
|
|
8
|
+
gaining range mode, marks, a value readout and an exact decimal step model. This
|
|
9
|
+
is a breaking change to both the component's value shape and its theme options.
|
|
10
|
+
|
|
11
|
+
**Why it could not stay native.** One `<input type="range">` cannot carry two
|
|
12
|
+
thumbs, so range mode, thumb crossing and per-thumb ARIA bounds were all
|
|
13
|
+
unreachable; marks and a value tooltip were unstyleable through it. The
|
|
14
|
+
alternative — a second component for the range case — would have meant two
|
|
15
|
+
keyboard implementations to keep in step, which is the drift the shared step
|
|
16
|
+
model exists to prevent. What the platform was giving us (the slider ARIA
|
|
17
|
+
pattern and the keyboard map) is reimplemented explicitly and covered by 29
|
|
18
|
+
specs.
|
|
19
|
+
|
|
20
|
+
**Breaking: value shape.**
|
|
21
|
+
|
|
22
|
+
```ts
|
|
23
|
+
// before
|
|
24
|
+
value = model<number>(0);
|
|
25
|
+
// after — the shape follows `mode`, and `null` is empty
|
|
26
|
+
value = model<number | UniNumberRange | null>(null);
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
A `single` slider still reads and writes a plain number, so
|
|
30
|
+
`[(value)]="volume"` is unchanged. Code that relied on `value()` being
|
|
31
|
+
non-nullable, or that read it without narrowing, now needs to handle `null` and
|
|
32
|
+
the `{ start, end }` range.
|
|
33
|
+
|
|
34
|
+
**Breaking: theme options.** `slider.options.color` is **removed**. Fill and
|
|
35
|
+
thumb colour now come from the `variant` role pair, the rule every other
|
|
36
|
+
component follows, so `variant="warn"` recolours a slider with no theme edit. A
|
|
37
|
+
theme that set `color` should delete it and pass `variant` at the call site.
|
|
38
|
+
`trackColor` now defaults to `primary-container` rather than `surface-variant`.
|
|
39
|
+
|
|
40
|
+
New options: `thumbBorderRadius`, `minTouchTarget`, `markSize`, `markColor`,
|
|
41
|
+
`labelTypeface`, `labelColor`, `tooltipColor`, `tooltipTextColor`,
|
|
42
|
+
`tooltipShadow`, `tooltipBorderRadius`, `transitionMs`. `trackHeight`,
|
|
43
|
+
`thumbSize` and `borderRadius` are unchanged.
|
|
44
|
+
|
|
45
|
+
**New capability.**
|
|
46
|
+
- `mode="range"` — two thumbs, a `{ start, end }` value, `minGap` to fence the
|
|
47
|
+
ends apart. Thumbs may cross and swap, and the dragged one keeps focus.
|
|
48
|
+
- `marks` and `snapToMarks` — labelled stops, spoken in place of the number.
|
|
49
|
+
- `valueDisplay` — `none`, `inline`, `tooltip`, or `input`, which seats a
|
|
50
|
+
compact `uni-number-input` at the trailing edge, two-way bound to the same
|
|
51
|
+
value: drag for the ballpark, type for the exact figure. Single mode only.
|
|
52
|
+
- `origin` — anchor the fill somewhere other than `min`, for sliders spanning ±.
|
|
53
|
+
- `sliding` and `changed` outputs, replacing an implicit per-frame model write.
|
|
54
|
+
**Bind `changed` in forms**; `sliding` fires every frame of a drag.
|
|
55
|
+
- `largeStep`, defaulting to a tenth of the range, for `PageUp`/`PageDown` and
|
|
56
|
+
`Shift+Arrow`.
|
|
57
|
+
- Right-to-left support: the horizontal arrows and the track mirror; the value
|
|
58
|
+
does not.
|
|
59
|
+
|
|
60
|
+
**Also new: the `cdk/number` primitives** this is built on, shared with the
|
|
61
|
+
numeric input family still to come — exact scaled-`BigInt` decimal arithmetic
|
|
62
|
+
(`stepDecimal`, `roundDecimal`, `clampDecimal`), locale-aware
|
|
63
|
+
`parseNumber`/`formatNumber` over `Intl`, and `createPressRepeat` for
|
|
64
|
+
hold-to-repeat stepper buttons. Stepping `0.1` twenty times from `0` now lands
|
|
65
|
+
on exactly `2`, and `1.15` rounds to `1.2` where `(1.15).toFixed(1)` gives
|
|
66
|
+
`'1.1'`.
|
|
67
|
+
|
|
68
|
+
### Minor Changes
|
|
69
|
+
|
|
70
|
+
- [`2a79bb8`](https://github.com/uni-design-system/uni/commit/2a79bb8ebd8fd0b5cd792697972b6f48b444c80f) Thanks [@gaenglish](https://github.com/gaenglish)! - New `uni-number-input`: the field for a quantity, a price, a percentage or a
|
|
71
|
+
measurement, with locale-aware parsing, `Intl` formatting on commit,
|
|
72
|
+
prefix/suffix adornments, min/max/step fences and steppers that hold to repeat.
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<uni-number-input label="Quantity" [(value)]="qty" [min]="1" />
|
|
76
|
+
<uni-number-input label="Unit price" currency="USD" [(value)]="price" />
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Why not `<input type="number">`.** Per the HTML value sanitization algorithm,
|
|
80
|
+
a number input whose text is not a valid floating-point number reports
|
|
81
|
+
`value === ''`. Type `12,50` as most of Europe does, or paste `1,234.56` from a
|
|
82
|
+
spreadsheet, and the app reads an empty field with no way to tell that from a
|
|
83
|
+
blank one — a data-loss bug, and the reason this is `type="text"` with
|
|
84
|
+
`role="spinbutton"`. The platform control also cannot group thousands, cannot
|
|
85
|
+
place an affix outside the editable text, has ~10px unstyleable spinners below
|
|
86
|
+
the WCAG 2.2 target minimum, changes value on the scroll wheel while focused,
|
|
87
|
+
and steps in floats.
|
|
88
|
+
|
|
89
|
+
**What it does instead.**
|
|
90
|
+
- **Presets** — `decimal`, `integer`, `currency`, `percent` — supply decimals,
|
|
91
|
+
grouping, affix and `inputmode` together, so a money field is `label`,
|
|
92
|
+
`currency="USD"`, `[(value)]`. `numberFormat` is the escape hatch, merged over
|
|
93
|
+
the preset.
|
|
94
|
+
- **Parses what people actually type**: canonical ASCII always, locale grouping
|
|
95
|
+
(`1.234,56` in German), pasted affixes and currency symbols, accounting
|
|
96
|
+
negatives `(1,234.56)`, localized digit systems, compact `1.5k`, and — behind
|
|
97
|
+
`allowExpressions` — spreadsheet arithmetic like `12*3`, via a shunting-yard
|
|
98
|
+
parser that never calls `eval`.
|
|
99
|
+
- **Unreadable text stays in the field**, flagged with a dashed underline and a
|
|
100
|
+
`rejected` event, rather than being silently swallowed.
|
|
101
|
+
- **Exact arithmetic.** Stepping `0.1` twenty times from `0` lands on exactly
|
|
102
|
+
`2`; `1.15` rounds to `1.2` where `(1.15).toFixed(1)` gives `'1.1'`. A second
|
|
103
|
+
`valueAsString` model carries digits a `number` cannot, and a dev-mode warning
|
|
104
|
+
fires when a bound `value` cannot round-trip.
|
|
105
|
+
- **Percent never divides behind your back**: `preset="percent"` shows `15%` for
|
|
106
|
+
`15`. Models that really are fractions set `valueIsFraction`.
|
|
107
|
+
- Clamping on commit rather than per keystroke, visible fences that disable the
|
|
108
|
+
matching stepper and announce, `wrap` for cyclic fields, `emptyStepValue`,
|
|
109
|
+
four stepper layouts, and hold-to-repeat that announces once on release.
|
|
110
|
+
|
|
111
|
+
`uni-slider` gains `valueDisplay="input"`, which seats one of these as its
|
|
112
|
+
readout — drag for the ballpark, type for the exact value.
|
|
113
|
+
|
|
114
|
+
Adds `numberInput` to `ComponentName` with a theme entry. Field chrome is not
|
|
115
|
+
duplicated there: colour, border, radius and focus come from the shared `input`
|
|
116
|
+
options via `uni-input-box`, so a number field restyles with every other field.
|
|
117
|
+
|
|
118
|
+
`uni-input-box` gains a `managedInset` input. The themed leading inset normally
|
|
119
|
+
rides the inner `<input>`, which is right while the text is the field's leading
|
|
120
|
+
edge and wrong the moment an adornment sits in front — a currency prefix would
|
|
121
|
+
hug the border while the number it belongs to sat indented past it. A field with
|
|
122
|
+
adornments sets `managedInset` and places the inset on whichever element is
|
|
123
|
+
actually first. Existing fields are unaffected: the default is `false`.
|
|
124
|
+
|
|
125
|
+
- [`e7875ee`](https://github.com/uni-design-system/uni/commit/e7875ee81030a703f4ca1904bb94cb8ddc7f57b9) Thanks [@gaenglish](https://github.com/gaenglish)! - New `uni-number-range-input`: two linked numeric fields in one chrome with a
|
|
126
|
+
single `{ start, end }` value — price filters, thresholds, tolerances. This
|
|
127
|
+
completes the numeric family alongside `uni-number-input`,
|
|
128
|
+
`uni-quantity-stepper` and the rebuilt `uni-slider`.
|
|
129
|
+
|
|
130
|
+
```html
|
|
131
|
+
<uni-number-range-input label="Price range" currency="USD" [(value)]="price" [minGap]="50" />
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`start`/`end` deliberately match `UniDateRange`, so the library has one range
|
|
135
|
+
vocabulary, and they never collide with the `min`/`max` **inputs**, which mean
|
|
136
|
+
the fence rather than the value.
|
|
137
|
+
|
|
138
|
+
**The rules that make it one field rather than two glued together:**
|
|
139
|
+
- **Either end alone is a valid value.** `{ start: 50 }` means "50 and up",
|
|
140
|
+
which is a real filter. This is where it diverges from `uni-date-time-input`,
|
|
141
|
+
whose two parts are two halves of one answer.
|
|
142
|
+
- **Stepping is fenced; typing swaps.** A stepper can never walk one end through
|
|
143
|
+
the other — its wall is the other end, held off by `minGap`, and each end's
|
|
144
|
+
`aria-valuemin`/`aria-valuemax` report that wall rather than the outer bounds.
|
|
145
|
+
A _typed_ backwards commit is swapped and announced instead, the rule
|
|
146
|
+
`uni-calendar` applies to a backwards date range: clamping against the other
|
|
147
|
+
end would destroy the number just entered.
|
|
148
|
+
- **`minGap` pushes the end you edited**, not the other one, which is what makes
|
|
149
|
+
stepping behave as a fence rather than dragging the range along.
|
|
150
|
+
- A refused draft flags only the end it was typed into; the other stays valid.
|
|
151
|
+
- `preset`, `currency`, `prefix`, `suffix`, `decimals`, `grouping`, `locale` and
|
|
152
|
+
`roundingMode` are forwarded to both ends so the halves always read alike.
|
|
153
|
+
|
|
154
|
+
It owns its commit path rather than nesting two `uni-number-input`s, because the
|
|
155
|
+
two behaviours above need _different_ bounds — a stepper must be fenced at the
|
|
156
|
+
other end while a typed commit must arrive un-clamped — and a child field
|
|
157
|
+
applies one bound pair to both. The arithmetic, parsing and formatting are still
|
|
158
|
+
the shared `cdk/number` primitives.
|
|
159
|
+
|
|
160
|
+
Adds `numberRangeInput` to `ComponentName` with a theme entry (`partGap`,
|
|
161
|
+
`dividerText`, `dividerColor`). Field chrome is not duplicated there: colour,
|
|
162
|
+
border, radius and focus come from the shared `input` options via
|
|
163
|
+
`uni-input-box`. `dividerText` is literal punctuation rather than an icon token —
|
|
164
|
+
an en dash between two numbers is not a glyph a theme swaps artwork for.
|
|
165
|
+
|
|
166
|
+
- [`589cecb`](https://github.com/uni-design-system/uni/commit/589cecb178d9119eea3fbc3f3cd9149eefdaa036) Thanks [@gaenglish](https://github.com/gaenglish)! - New `uni-quantity-stepper`: `− 3 +` for cart lines, table cells and seat counts
|
|
167
|
+
— the numeric core with no field chrome, no label and no room for either.
|
|
168
|
+
|
|
169
|
+
```html
|
|
170
|
+
<uni-quantity-stepper label="Quantity, Blue T-shirt (M)" [(value)]="qty" [min]="1" />
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
A separate component rather than a `chrome="bare"` flag on `uni-number-input`,
|
|
174
|
+
because this control is defined by what it does _not_ have — presets, affixes,
|
|
175
|
+
expressions, four stepper layouts — and eight inputs are easier to write
|
|
176
|
+
correctly than forty plus a list of which ones to leave alone. The arithmetic,
|
|
177
|
+
parsing and hold-to-repeat come from the same `cdk/number` primitives, so
|
|
178
|
+
`1,200` and the keyboard map behave identically in both.
|
|
179
|
+
- **`deleteAtMin`** is the cart pattern in one attribute: at the floor the
|
|
180
|
+
decrement becomes a remove affordance, renamed `Remove {label}`, and emits
|
|
181
|
+
`removed` rather than stepping to zero. Without it every shop reimplements the
|
|
182
|
+
same `value === 1 ? remove() : step(-1)` branch outside the component. (The
|
|
183
|
+
spec called this output `emptied`; that is a native `HTMLMediaElement` event
|
|
184
|
+
name, which `@angular-eslint/no-output-native` rightly rejects, and `removed`
|
|
185
|
+
is already what `uni-tag` calls the same request.)
|
|
186
|
+
- The middle is a real input by default — typing `12` beats tapping `+` eleven
|
|
187
|
+
times, and it takes the same grouped and locale-aware entry the field does.
|
|
188
|
+
`editable=false` renders the number as text for read-mostly tables, and the
|
|
189
|
+
buttons become the tab stops since there is nothing else to focus.
|
|
190
|
+
- `size` is `sm` / `md` / `lg` at 24 / 32 / 40px _outer_ height, so an `md`
|
|
191
|
+
stepper lines up with a 32px field beside it, with the buttons square at that
|
|
192
|
+
height. `md` and `lg` clear the 24×24 pointer target of WCAG 2.2 SC 2.5.8;
|
|
193
|
+
`sm` leaves 22px inside its border and is the dense desktop option.
|
|
194
|
+
|
|
195
|
+
Adds `quantityStepper` to `ComponentName` with a theme entry. Unlike the other
|
|
196
|
+
numeric controls it does **not** inherit the shared `input` chrome — it is not a
|
|
197
|
+
field — so it carries its own container tokens, defaulted to the same values
|
|
198
|
+
`input` uses so a cart stepper and a form field look related out of the box.
|
|
199
|
+
Height comes from the entry's `sizes` block rather than an option.
|
|
200
|
+
|
|
201
|
+
## 9.0.1
|
|
202
|
+
|
|
203
|
+
### Patch Changes
|
|
204
|
+
|
|
205
|
+
- [`f926cd5`](https://github.com/uni-design-system/uni/commit/f926cd513a5cac593adef559e21bada4dada76ee) Thanks [@gaenglish](https://github.com/gaenglish)! - `uni-react`'s Switch reads the `success` color token instead of hand-rolling an
|
|
206
|
+
HSL string from a color-generation internal, and both packages now typecheck as
|
|
207
|
+
part of their build.
|
|
208
|
+
|
|
209
|
+
The Switch built its "on" color as `hsl(${RoleHues.success.default}, 32%, 50%)`
|
|
210
|
+
— a fixed green assembled from the HSL generation tables rather than the theme,
|
|
211
|
+
so it never recolored with the theme and broke when those tables were removed.
|
|
212
|
+
It now reads `useTheme().colors.success`.
|
|
213
|
+
|
|
214
|
+
The reason that reached a deploy is the build. `vite build` transpiles with
|
|
215
|
+
esbuild, which strips types without checking them, and it treats
|
|
216
|
+
`@uni-design-system/uni-core` as an external — so neither the type layer nor the
|
|
217
|
+
module graph ever verified that an imported core export exists. `pnpm turbo run
|
|
218
|
+
build` passed on a package whose source did not compile.
|
|
219
|
+
- `core` and `react` now run `tsc --noEmit` as the first half of `build`, so a
|
|
220
|
+
removed or renamed core export fails the consumer's build.
|
|
221
|
+
- A `type-check` turbo task exists for running that pass alone.
|
|
222
|
+
- CI builds **both** Storybooks, not just Angular's. These bundle uni-core
|
|
223
|
+
instead of externalizing it, so they are the step that resolves its exports
|
|
224
|
+
against real consumer source.
|
|
225
|
+
|
|
226
|
+
This also cleared four pre-existing type errors in `IconTextRow`, which did
|
|
227
|
+
arithmetic on `fontSize` / `lineHeight` — typed `CssLength` (`number | string`)
|
|
228
|
+
— and passed the result to props typed `number`. They are coerced through one
|
|
229
|
+
documented helper now.
|
|
230
|
+
|
|
3
231
|
## 9.0.0
|
|
4
232
|
|
|
5
233
|
### Major Changes
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -1294,6 +1294,47 @@ var buildComponents = (c) => ({
|
|
|
1294
1294
|
rows: 3,
|
|
1295
1295
|
resize: "vertical"
|
|
1296
1296
|
} },
|
|
1297
|
+
numberInput: { options: {
|
|
1298
|
+
stepperLayout: "stacked",
|
|
1299
|
+
incrementIcon: "plus",
|
|
1300
|
+
decrementIcon: "minus",
|
|
1301
|
+
stepUpIcon: "chevronUp",
|
|
1302
|
+
stepDownIcon: "chevronDown",
|
|
1303
|
+
stepperWidth: 32,
|
|
1304
|
+
minTouchTarget: 24,
|
|
1305
|
+
affixColor: "on-primary-surface-variant",
|
|
1306
|
+
affixGap: "xs",
|
|
1307
|
+
align: "start",
|
|
1308
|
+
tabularNumerals: true,
|
|
1309
|
+
repeatDelayMs: 500,
|
|
1310
|
+
repeatIntervalMs: 100,
|
|
1311
|
+
repeatFastIntervalMs: 25,
|
|
1312
|
+
repeatRampMs: 2e3
|
|
1313
|
+
} },
|
|
1314
|
+
numberRangeInput: { options: {
|
|
1315
|
+
partGap: "sm",
|
|
1316
|
+
dividerText: "–",
|
|
1317
|
+
dividerColor: "outline",
|
|
1318
|
+
affixColor: "on-primary-surface-variant",
|
|
1319
|
+
affixGap: "xs"
|
|
1320
|
+
} },
|
|
1321
|
+
quantityStepper: {
|
|
1322
|
+
options: {
|
|
1323
|
+
color: "primary-surface",
|
|
1324
|
+
border: "light",
|
|
1325
|
+
borderRadius: "xs",
|
|
1326
|
+
incrementIcon: "plus",
|
|
1327
|
+
decrementIcon: "minus",
|
|
1328
|
+
deleteIcon: "delete",
|
|
1329
|
+
tabularNumerals: true,
|
|
1330
|
+
valueWidth: "3ch"
|
|
1331
|
+
},
|
|
1332
|
+
sizes: {
|
|
1333
|
+
sm: { height: 24 },
|
|
1334
|
+
md: { height: 32 },
|
|
1335
|
+
lg: { height: 40 }
|
|
1336
|
+
}
|
|
1337
|
+
},
|
|
1297
1338
|
tabs: { options: {
|
|
1298
1339
|
typeface: "title-small",
|
|
1299
1340
|
textColor: "on-surface-variant",
|
|
@@ -1717,11 +1758,21 @@ var buildComponents = (c) => ({
|
|
|
1717
1758
|
gap: "xxs"
|
|
1718
1759
|
} },
|
|
1719
1760
|
slider: { options: {
|
|
1720
|
-
color: "primary",
|
|
1721
|
-
trackColor: "surface-variant",
|
|
1722
|
-
borderRadius: "max",
|
|
1723
1761
|
trackHeight: 4,
|
|
1724
|
-
|
|
1762
|
+
trackColor: "primary-container",
|
|
1763
|
+
borderRadius: "max",
|
|
1764
|
+
thumbSize: 16,
|
|
1765
|
+
thumbBorderRadius: "max",
|
|
1766
|
+
minTouchTarget: 24,
|
|
1767
|
+
markSize: 3,
|
|
1768
|
+
markColor: "on-primary-container",
|
|
1769
|
+
labelTypeface: "label",
|
|
1770
|
+
labelColor: "on-surface-variant",
|
|
1771
|
+
tooltipColor: "inverse-surface",
|
|
1772
|
+
tooltipTextColor: "on-inverse-surface",
|
|
1773
|
+
tooltipShadow: "menu",
|
|
1774
|
+
tooltipBorderRadius: "xs",
|
|
1775
|
+
transitionMs: 120
|
|
1725
1776
|
} },
|
|
1726
1777
|
skeleton: { options: {
|
|
1727
1778
|
color: "surface-variant",
|