@object-ui/fields 17.3.0 → 17.5.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 +941 -0
- package/README.md +1 -12
- package/dist/FieldEditWidget.d.ts +7 -1
- package/dist/currency.d.ts +46 -0
- package/dist/field-type-alias.d.ts +19 -1
- package/dist/index.cjs +4 -4
- package/dist/index.css +633 -0
- package/dist/index.d.ts +48 -12
- package/dist/index.js +5026 -4933
- package/dist/widgets/AddressField.d.ts +3 -11
- package/dist/widgets/FullscreenFieldEditor.d.ts +42 -152
- package/dist/widgets/GridField.d.ts +12 -2
- package/dist/widgets/OptionsEmptyState.d.ts +15 -1
- package/dist/widgets/RecordPickerDialog.d.ts +32 -6
- package/dist/widgets/SelectField.d.ts +25 -5
- package/dist/widgets/address-format.d.ts +68 -0
- package/dist/widgets/file-size-guard.d.ts +41 -0
- package/dist/widgets/nativeDateValue.d.ts +37 -0
- package/dist/widgets/toDomProps.d.ts +30 -10
- package/dist/widgets/toHostGroupProps.d.ts +91 -0
- package/dist/widgets/useRecordQuery.d.ts +7 -1
- package/package.json +17 -13
- package/src/FieldEditWidget.tsx +17 -1
- package/src/__tests__/AddressCellRenderer.test.tsx +166 -0
- package/src/__tests__/CurrencyField.minorUnits.test.tsx +191 -0
- package/src/__tests__/CurrencyField.symbol.test.tsx +198 -0
- package/src/__tests__/DateCellRenderer.test.tsx +9 -0
- package/src/__tests__/NumberCellRenderer.grouping.test.tsx +146 -0
- package/src/__tests__/PercentCellRenderer.locale.test.tsx +152 -0
- package/src/__tests__/PercentCellRenderer.test.tsx +115 -0
- package/src/__tests__/boolean-label-association-e2e.test.tsx +298 -0
- package/src/__tests__/capability-multiselect-retired.test.ts +109 -0
- package/src/__tests__/composite-group-label-e2e.test.tsx +436 -0
- package/src/__tests__/composite-group-label-readonly-e2e.test.tsx +403 -0
- package/src/__tests__/date-formatter-residue-4272.test.ts +120 -0
- package/src/__tests__/date-locale-channel.test.tsx +305 -0
- package/src/__tests__/formatCurrency.centsDigit.test.tsx +158 -0
- package/src/__tests__/formatCurrency.minorUnits.test.tsx +221 -0
- package/src/__tests__/group-labelling-declaration.test.ts +148 -0
- package/src/__tests__/lookupCellRecordLink.test.tsx +171 -0
- package/src/__tests__/percent-cell-vs-measure-4576.test.ts +115 -0
- package/src/__tests__/percent-formatter-locale-4553.test.ts +147 -0
- package/src/__tests__/percent-tie-halfup-4590.test.ts +224 -0
- package/src/__tests__/select-label-association-e2e.test.tsx +199 -0
- package/src/__tests__/widget-dom-leak-e2e.test.tsx +29 -270
- package/src/complex-widgets.test.tsx +22 -6
- package/src/currency.ts +130 -0
- package/src/datetime-widgets.test.tsx +94 -2
- package/src/field-type-alias.multiple.test.ts +81 -0
- package/src/field-type-alias.ts +58 -2
- package/src/index.css +44 -0
- package/src/index.tsx +489 -247
- package/src/standard-widgets.test.tsx +8 -1
- package/src/widgets/AddressField.postalCode.test.tsx +257 -0
- package/src/widgets/AddressField.tsx +79 -29
- package/src/widgets/AddressField.uniqueIds.test.tsx +2 -1
- package/src/widgets/BooleanField.tsx +41 -7
- package/src/widgets/CapabilityMultiSelectField.tsx +17 -5
- package/src/widgets/CheckboxesField.tsx +35 -2
- package/src/widgets/CurrencyField.tsx +55 -15
- package/src/widgets/DateField.tsx +11 -2
- package/src/widgets/DateTimeField.tsx +12 -3
- package/src/widgets/FileField.tsx +27 -9
- package/src/widgets/FormulaField.tsx +6 -1
- package/src/widgets/FullscreenFieldEditor.tsx +47 -258
- package/src/widgets/GeolocationField.tsx +29 -3
- package/src/widgets/GridField.test.tsx +226 -0
- package/src/widgets/GridField.tsx +114 -10
- package/src/widgets/ImageField.maxSize.test.tsx +154 -0
- package/src/widgets/ImageField.tsx +54 -4
- package/src/widgets/LookupField.hydration.test.tsx +1 -1
- package/src/widgets/LookupField.tsx +8 -4
- package/src/widgets/MultiSelectField.tsx +56 -2
- package/src/widgets/OptionsEmptyState.tsx +16 -0
- package/src/widgets/RadioField.tsx +35 -3
- package/src/widgets/RatingField.tsx +15 -2
- package/src/widgets/RecordPickerDialog.baseFilterShapes.test.tsx +191 -0
- package/src/widgets/RecordPickerDialog.dateLocale.test.tsx +124 -0
- package/src/widgets/RecordPickerDialog.tsx +64 -15
- package/src/widgets/RichTextField.tsx +1 -1
- package/src/widgets/SelectField.tsx +36 -5
- package/src/widgets/UserField.tsx +3 -2
- package/src/widgets/__tests__/FilterConditionField.operators.test.ts +25 -1
- package/src/widgets/address-format.ts +120 -0
- package/src/widgets/file-size-guard.ts +55 -0
- package/src/widgets/nativeDateValue.test.ts +115 -0
- package/src/widgets/nativeDateValue.ts +112 -0
- package/src/widgets/optionWidgets.gatedOptions.test.tsx +267 -0
- package/src/widgets/optionWidgets.unconfiguredOptions.test.tsx +150 -0
- package/src/widgets/toDomProps.ts +48 -19
- package/src/widgets/toHostGroupProps.ts +102 -0
- package/src/widgets/useFieldTranslation.ts +15 -33
- package/src/widgets/useRecordQuery.ts +30 -3
- package/dist/FieldEditWidget.test.d.ts +0 -8
- package/dist/__tests__/DateCellRenderer.test.d.ts +0 -0
- package/dist/__tests__/NumberCellRenderer.test.d.ts +0 -0
- package/dist/__tests__/cell-truncation.test.d.ts +0 -0
- package/dist/__tests__/field-carrier-sdui.test.d.ts +0 -0
- package/dist/__tests__/lookupCellDisplayField.test.d.ts +0 -0
- package/dist/__tests__/lookupCellDisplayName.test.d.ts +0 -0
- package/dist/__tests__/lookupCellReferenceKey.test.d.ts +0 -0
- package/dist/__tests__/registry-collision.test.d.ts +0 -0
- package/dist/__tests__/resolveFieldCurrency.test.d.ts +0 -1
- package/dist/__tests__/spec-symbol-batch7.test.d.ts +0 -8
- package/dist/__tests__/validation-feedback.test.d.ts +0 -0
- package/dist/__tests__/widget-aria-invalid-e2e.test.d.ts +0 -0
- package/dist/__tests__/widget-aria-invalid-registry-e2e.test.d.ts +0 -0
- package/dist/__tests__/widget-dom-leak-e2e.test.d.ts +0 -0
- package/dist/__tests__/widget-props-contract.test.d.ts +0 -8
- package/dist/coerce-safe-value.test.d.ts +0 -1
- package/dist/complex-widgets.test.d.ts +0 -1
- package/dist/datetime-widgets.test.d.ts +0 -1
- package/dist/field-type-coverage.test.d.ts +0 -1
- package/dist/standard-widgets.test.d.ts +0 -0
- package/dist/widgets/AddressField.uniqueIds.test.d.ts +0 -0
- package/dist/widgets/CapabilityMultiSelectField.test.d.ts +0 -0
- package/dist/widgets/CheckboxesField.cascade.test.d.ts +0 -0
- package/dist/widgets/GeolocationField.uniqueIds.test.d.ts +0 -0
- package/dist/widgets/GridField.test.d.ts +0 -1
- package/dist/widgets/ImageLightbox.test.d.ts +0 -1
- package/dist/widgets/LookupField.dependsOn.test.d.ts +0 -8
- package/dist/widgets/LookupField.gateHintLabel.test.d.ts +0 -8
- package/dist/widgets/LookupField.hydration.test.d.ts +0 -1
- package/dist/widgets/LookupField.idField.test.d.ts +0 -1
- package/dist/widgets/MultiSelectField.cascade.test.d.ts +0 -0
- package/dist/widgets/OptionsEmptyState.no-provider.test.d.ts +0 -0
- package/dist/widgets/OptionsEmptyState.test.d.ts +0 -0
- package/dist/widgets/PeoplePicker.test.d.ts +0 -8
- package/dist/widgets/PeoplePickerComponents.test.d.ts +0 -8
- package/dist/widgets/RadioField.cascade.test.d.ts +0 -0
- package/dist/widgets/RecipientPickerField.test.d.ts +0 -0
- package/dist/widgets/RecordPickerDialog.filterOptions.test.d.ts +0 -8
- package/dist/widgets/RecordPickerDialog.selectLabel.test.d.ts +0 -8
- package/dist/widgets/SelectField.cascade.test.d.ts +0 -0
- package/dist/widgets/TagsField.placeholder.no-provider.test.d.ts +0 -0
- package/dist/widgets/TagsField.placeholder.test.d.ts +0 -0
- package/dist/widgets/UserFieldPicker.test.d.ts +0 -8
- package/dist/widgets/__tests__/FilterConditionField.matchAll.test.d.ts +0 -8
- package/dist/widgets/__tests__/FilterConditionField.operators.test.d.ts +0 -8
- package/dist/widgets/__tests__/FullscreenFieldEditor.i18n.test.d.ts +0 -0
- package/dist/widgets/__tests__/FullscreenFieldEditor.no-provider.test.d.ts +0 -0
- package/dist/widgets/__tests__/RichTextField.fullscreenDisabled.test.d.ts +0 -0
- package/dist/widgets/__tests__/RichTextField.mobileFullscreen.test.d.ts +0 -0
- package/dist/widgets/__tests__/TextAreaField.characterCount.announcements.test.d.ts +0 -0
- package/dist/widgets/__tests__/TextAreaField.characterCount.i18n.test.d.ts +0 -0
- package/dist/widgets/__tests__/TextAreaField.characterCount.no-provider.test.d.ts +0 -0
- package/dist/widgets/__tests__/TextAreaField.fullscreenCharacterCount.i18n.test.d.ts +0 -0
- package/dist/widgets/__tests__/TextAreaField.fullscreenCharacterCount.test.d.ts +0 -0
- package/dist/widgets/__tests__/TextAreaField.fullscreenDisabled.test.d.ts +0 -0
- package/dist/widgets/__tests__/TextAreaField.mobileFullscreen.test.d.ts +0 -0
- package/dist/widgets/deriveLookupColumns.test.d.ts +0 -1
- package/dist/widgets/file-value.test.d.ts +0 -1
- package/dist/widgets/personDisplay.test.d.ts +0 -8
- package/dist/widgets/recentLookups.test.d.ts +0 -1
- package/dist/widgets/useRecordQuery.test.d.ts +0 -8
- package/dist/widgets/useUploadingSignal.test.d.ts +0 -1
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* The widget id is a function of the (type, `multiple`) PAIR, not of the type
|
|
11
|
+
* string alone (objectui#3986).
|
|
12
|
+
*
|
|
13
|
+
* `mapFieldTypeToFormType` mapped `select` to `field:select` unconditionally,
|
|
14
|
+
* while `SelectField` delegated to `MultiSelectField` whenever the metadata said
|
|
15
|
+
* `multiple`. Three correct pieces, one gap between them: the component that
|
|
16
|
+
* RENDERED was `MultiSelectField`, but everything keyed on the widget id — above
|
|
17
|
+
* all the label-association declaration (`ComponentMeta.labelling`, resolved via
|
|
18
|
+
* `getMeta('select')`) — was still answering for the single-value combobox. The
|
|
19
|
+
* host label of a normal `{ type: 'select', multiple: true }` picklist therefore
|
|
20
|
+
* emitted a `for` at the chip row's wrapper `div`, where a `for` is inert.
|
|
21
|
+
*
|
|
22
|
+
* `select` cannot simply be declared `labelling: 'group'` instead: the
|
|
23
|
+
* single-value trigger IS labelable, and a bare `select` is a builtin the form
|
|
24
|
+
* renderer resolves without the registry at all (pinned in
|
|
25
|
+
* `form-group-label-association.test.ts`). The producer has to name the widget
|
|
26
|
+
* that renders, which is what this file pins.
|
|
27
|
+
*
|
|
28
|
+
* Metadata only — nothing renders here, so no widget module is loaded.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { describe, it, expect } from 'vitest';
|
|
32
|
+
import { mapFieldTypeToFormType } from './field-type-alias';
|
|
33
|
+
|
|
34
|
+
describe('select carries its arity in the widget id (objectui#3986)', () => {
|
|
35
|
+
it('maps select + multiple to the multi-value widget', () => {
|
|
36
|
+
// The one assertion that was `field:select` before this change.
|
|
37
|
+
expect(mapFieldTypeToFormType('select', { multiple: true })).toBe('field:multiselect');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('keeps the single-value widget without multiple, and for multiple: false', () => {
|
|
41
|
+
// The guard direction: single-select must not move. Its trigger is a
|
|
42
|
+
// labelable `button[role=combobox]` and its `for` association works — taking
|
|
43
|
+
// that away would break a field that is fine to fix one that is not.
|
|
44
|
+
expect(mapFieldTypeToFormType('select')).toBe('field:select');
|
|
45
|
+
expect(mapFieldTypeToFormType('select', {})).toBe('field:select');
|
|
46
|
+
expect(mapFieldTypeToFormType('select', { multiple: false })).toBe('field:select');
|
|
47
|
+
expect(mapFieldTypeToFormType('select', { multiple: null })).toBe('field:select');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('is idempotent for the type that is already inherently multi', () => {
|
|
51
|
+
// `multiselect` is a type in its own right; the arity override must not turn
|
|
52
|
+
// it into something else, whichever way the flag is set.
|
|
53
|
+
expect(mapFieldTypeToFormType('multiselect')).toBe('field:multiselect');
|
|
54
|
+
expect(mapFieldTypeToFormType('multiselect', { multiple: true })).toBe('field:multiselect');
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The spec's multi-capable set is larger than the widget-moving set, and the
|
|
59
|
+
* difference is the whole reason this override is table-driven rather than a
|
|
60
|
+
* `config.multiple` branch sprinkled per type:
|
|
61
|
+
*
|
|
62
|
+
* `MULTI_CAPABLE_TYPES` = select / lookup / file / image (+ `radio` on the
|
|
63
|
+
* select branch, `user` storing like `lookup`)
|
|
64
|
+
*
|
|
65
|
+
* Every member except `select` renders BOTH arities inside one widget —
|
|
66
|
+
* `LookupField`, `FileField`, `ImageField` each read `multiple` themselves — so
|
|
67
|
+
* their widget id, and with it their `labelling` declaration, is correct for
|
|
68
|
+
* either arity. Moving them would point at widgets that do not exist.
|
|
69
|
+
*/
|
|
70
|
+
const UNMOVED_MULTI_CAPABLE = ['lookup', 'master_detail', 'user', 'owner', 'file', 'image', 'radio'] as const;
|
|
71
|
+
|
|
72
|
+
it.each(UNMOVED_MULTI_CAPABLE)('%s resolves identically with and without multiple', (type) => {
|
|
73
|
+
expect(mapFieldTypeToFormType(type, { multiple: true })).toBe(mapFieldTypeToFormType(type));
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('does not invent a widget for an unknown type flagged multiple', () => {
|
|
77
|
+
// The fallback is unchanged: an unknown type is `field:text` at either arity,
|
|
78
|
+
// never `field:text-multiple`-anything.
|
|
79
|
+
expect(mapFieldTypeToFormType('something-unknown', { multiple: true })).toBe('field:text');
|
|
80
|
+
});
|
|
81
|
+
});
|
package/src/field-type-alias.ts
CHANGED
|
@@ -6,15 +6,63 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* The slice of a field definition the widget decision reads beyond `type`.
|
|
11
|
+
*
|
|
12
|
+
* Structural (not the spec `Field`) for the same reason the spec's own
|
|
13
|
+
* `ValueShapeFieldDef` is: every caller — object-schema metadata, a spec
|
|
14
|
+
* `FormFieldSchema` override, an action param def — can pass its own trimmed
|
|
15
|
+
* shape verbatim. `multiple` is the only key read; nothing else here is
|
|
16
|
+
* consulted, so a caller that has the whole metadata object may hand it over
|
|
17
|
+
* as-is.
|
|
18
|
+
*/
|
|
19
|
+
export interface FieldTypeMappingConfig {
|
|
20
|
+
/** `FieldSchema.multiple` — the field holds zero-or-more values. */
|
|
21
|
+
multiple?: boolean | null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Field types whose `multiple: true` form is a DIFFERENT registered widget,
|
|
26
|
+
* rather than the same widget in another mode (objectui#3986).
|
|
27
|
+
*
|
|
28
|
+
* `select` is the only member, and the narrowness is measured, not assumed. The
|
|
29
|
+
* spec's `MULTI_CAPABLE_TYPES` is larger — select / lookup / file / image, with
|
|
30
|
+
* `radio` on the select branch and `user` storing like `lookup` — but every
|
|
31
|
+
* other member renders both arities INSIDE one widget: `LookupField`,
|
|
32
|
+
* `FileField` and `ImageField` each branch on `multiple` themselves, so their
|
|
33
|
+
* registry id, and with it their `labelling` declaration, is the same either
|
|
34
|
+
* way. A `select` declared `multiple: true` renders `MultiSelectField` instead:
|
|
35
|
+
* a different component, whose labelled surface is a chip row's container that
|
|
36
|
+
* a `<label for>` cannot address (it must be named by IDREF, which is what
|
|
37
|
+
* `field:multiselect`'s `labelling: 'group'` declares — objectui#3975/#3961).
|
|
38
|
+
*
|
|
39
|
+
* So the widget id has to carry the arity. When it did not, the host label was
|
|
40
|
+
* associated by the declaration registered under `select` — a single-value
|
|
41
|
+
* combobox that was NOT rendering — and the visible label of a normal
|
|
42
|
+
* `{ type: 'select', multiple: true }` picklist named nothing at all. One place
|
|
43
|
+
* decides which widget renders, so the declaration and the render cannot
|
|
44
|
+
* disagree again.
|
|
45
|
+
*/
|
|
46
|
+
const MULTI_VALUE_FORM_TYPES: Record<string, string> = {
|
|
47
|
+
select: 'field:multiselect',
|
|
48
|
+
};
|
|
49
|
+
|
|
9
50
|
/**
|
|
10
51
|
* Map field type to form component type
|
|
11
|
-
*
|
|
52
|
+
*
|
|
12
53
|
* @param fieldType - The ObjectQL field type identifier to convert
|
|
13
54
|
* (for example: `"text"`, `"number"`, `"date"`, `"lookup"`).
|
|
55
|
+
* @param config - The rest of the field definition, for the types whose widget
|
|
56
|
+
* identity depends on more than the type string. Only `multiple` is read; see
|
|
57
|
+
* {@link MULTI_VALUE_FORM_TYPES}. Omitting it maps the single-value form, which
|
|
58
|
+
* is what every non-multi-capable type resolves to anyway.
|
|
14
59
|
* @returns The normalized form field type string used in the form schema
|
|
15
60
|
* (for example: `"input"`, `"textarea"`, `"date-picker"`, `"select"`).
|
|
16
61
|
*/
|
|
17
|
-
export function mapFieldTypeToFormType(
|
|
62
|
+
export function mapFieldTypeToFormType(
|
|
63
|
+
fieldType: string,
|
|
64
|
+
config?: FieldTypeMappingConfig,
|
|
65
|
+
): string {
|
|
18
66
|
const typeMap: Record<string, string> = {
|
|
19
67
|
// Text-based fields
|
|
20
68
|
text: 'field:text',
|
|
@@ -96,5 +144,13 @@ export function mapFieldTypeToFormType(fieldType: string): string {
|
|
|
96
144
|
auto_number: 'field:auto_number',
|
|
97
145
|
};
|
|
98
146
|
|
|
147
|
+
// The arity override comes FIRST and is table-driven: only a type listed in
|
|
148
|
+
// `MULTI_VALUE_FORM_TYPES` has a second widget to move to, so `multiple` on
|
|
149
|
+
// any other type (a multi `lookup`, a multi `file`) resolves exactly as
|
|
150
|
+
// before and keeps reaching the widget that handles both arities itself.
|
|
151
|
+
if (config?.multiple && MULTI_VALUE_FORM_TYPES[fieldType]) {
|
|
152
|
+
return MULTI_VALUE_FORM_TYPES[fieldType];
|
|
153
|
+
}
|
|
154
|
+
|
|
99
155
|
return typeMap[fieldType] || 'field:text';
|
|
100
156
|
}
|
package/src/index.css
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Tailwind entry for `@object-ui/fields` — BUILD-TIME ONLY.
|
|
3
|
+
*
|
|
4
|
+
* Consumers never compile this file. They import the compiled artifact:
|
|
5
|
+
*
|
|
6
|
+
* @import '@object-ui/components/style.css';
|
|
7
|
+
* @import '@object-ui/fields/style.css'; <- ./dist/index.css, built from this
|
|
8
|
+
*
|
|
9
|
+
* The `@reference` below is what makes the "narrow" shape possible
|
|
10
|
+
* (objectui#4059): it gives this compilation `@object-ui/components`' theme
|
|
11
|
+
* tokens, its class-based `dark` variant and its `tailwindcss-animate` plugin
|
|
12
|
+
* WITHOUT emitting a single byte of them. So the sheet built from this entry
|
|
13
|
+
* carries utilities only — no preflight, no `@theme` `:root` block, no base
|
|
14
|
+
* layer. `@object-ui/components`' own stylesheet owns all of that, and
|
|
15
|
+
* `scripts/build-css.mjs` then subtracts every rule that sheet already ships.
|
|
16
|
+
*
|
|
17
|
+
* That is why the import ORDER above is not cosmetic: this sheet is a
|
|
18
|
+
* supplement to the components sheet, not a replacement for it.
|
|
19
|
+
*
|
|
20
|
+
* This file has no `@import 'tailwindcss'` on purpose — that would pull in
|
|
21
|
+
* preflight and re-emit the shared theme, which is exactly the ~160 kB
|
|
22
|
+
* duplication the narrow variant exists to avoid.
|
|
23
|
+
*/
|
|
24
|
+
@reference '../../components/src/index.css';
|
|
25
|
+
|
|
26
|
+
/*
|
|
27
|
+
* `source(none)` is load-bearing, not tidiness. Tailwind's automatic source
|
|
28
|
+
* detection resolves against the PROCESS CWD, and `@reference` above pulls in
|
|
29
|
+
* components' entry, whose own `@import 'tailwindcss'` turns that detection on.
|
|
30
|
+
* Without `source(none)` the candidate set therefore depends on where the build
|
|
31
|
+
* was launched from: run from this package it scanned `packages/fields` and
|
|
32
|
+
* produced a 21 kB sheet, run from the repo root it scanned the whole workspace
|
|
33
|
+
* and produced a 287 kB one full of other packages' utilities. Same commit, same
|
|
34
|
+
* command, two different published artifacts.
|
|
35
|
+
*
|
|
36
|
+
* With it, the ONLY inputs are the explicit `@source` lines below, and the
|
|
37
|
+
* output is byte-identical from any working directory.
|
|
38
|
+
*/
|
|
39
|
+
@import 'tailwindcss/utilities.css' layer(utilities) source(none);
|
|
40
|
+
|
|
41
|
+
/* Only shipped source: `*.test.tsx` never reaches a consumer, so utilities used
|
|
42
|
+
solely by tests must not be compiled into the published sheet. */
|
|
43
|
+
@source './**/*.{ts,tsx}';
|
|
44
|
+
@source not './**/*.test.{ts,tsx}';
|