rei-kit 3.3.0 → 3.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/README.md CHANGED
@@ -165,7 +165,7 @@ app, and the case *least* favourable to this kit:
165
165
 
166
166
  | Kit | JS | CSS | Total |
167
167
  | -------------------- | ---------: | ----------: | ----------: |
168
- | **rei-kit 3.3.0** | **3.6 KB** | **23.1 KB** | **26.8 KB** |
168
+ | **rei-kit 3.5.0** | **3.7 KB** | **23.1 KB** | **26.8 KB** |
169
169
  | element-plus 2.14.6 | 27.3 KB | 6.0 KB | 33.3 KB |
170
170
  | naive-ui 2.45.3 | 51.2 KB | — | 51.2 KB |
171
171
  | primevue 5.0.1 | 53.6 KB | — | 53.6 KB |
@@ -177,7 +177,7 @@ a data table, a tooltip and a card. A screen rather than a demo:
177
177
 
178
178
  | Kit | JS | CSS | Total |
179
179
  | -------------------- | ---------: | ----------: | -----------: |
180
- | **rei-kit 3.3.0** | **8.6 KB** | **23.1 KB** | **31.7 KB** |
180
+ | **rei-kit 3.5.0** | **8.6 KB** | **23.1 KB** | **31.7 KB** |
181
181
  | element-plus 2.14.6 | 90.1 KB | 14.0 KB | 104.1 KB |
182
182
  | naive-ui 2.45.3 | 132.4 KB | — | 132.4 KB |
183
183
  | primevue 5.0.1 | 135.8 KB | — | 135.8 KB |
@@ -234,7 +234,7 @@ Each claim here is enforced by something that fails, not by a promise.
234
234
 
235
235
  ## Status
236
236
 
237
- **v3.3.0 — three consumers.**
237
+ **v3.5.0 — three consumers.**
238
238
 
239
239
  | | |
240
240
  | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
package/dist/app.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { a as BaseCheckbox_default, o as BaseSheet_default, r as horizontalStep, s as inertOutside, t as focusTarget } from "./focus-target-BtcoJdmz.js";
2
- import { _ as toRedirectPath, c as useToast, d as isThemePreference, g as safeRedirect, h as tapFeedback, i as BaseInput_default, l as useOnline, m as useTheme, r as GoogleButton_default, s as BaseAlert_default, t as announce } from "./use-announce-D8SKsiqn.js";
2
+ import { _ as toRedirectPath, c as useToast, d as isThemePreference, g as safeRedirect, h as tapFeedback, i as BaseInput_default, l as useOnline, m as useTheme, r as GoogleButton_default, s as BaseAlert_default, t as announce } from "./use-announce-BGZnV78W.js";
3
3
  import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BOaGB7Aw.js";
4
4
  import { t as BaseButton_default } from "./BaseButton-BD2HKB1L.js";
5
5
  import { t as SettingsRow_default } from "./SettingsRow-C6Spi7Np.js";
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The wiring that fails silently, checked at unit-test speed.
3
+ *
4
+ * Every line of this package's install can be left out and leave a build that
5
+ * is green: a missing `@source` means Tailwind never emits the utilities the
6
+ * components ask for, a missing stylesheet import means the components keep
7
+ * their markup and lose their layout, and a colour role the app never defines
8
+ * makes `bg-primary` emit no declaration at all. None of it is visible to
9
+ * `vue-tsc`, to a component test, or to a reader of the diff. One of the apps
10
+ * in this family shipped a release with its tab bar invisible exactly this
11
+ * way.
12
+ *
13
+ * Both apps then wrote the same check, independently, with three of the four
14
+ * assertions carrying the same names — which is this kit's own test for a
15
+ * missing part. So the check moved here, and it knows one thing their copies
16
+ * could not: that the preset exists and carries the `@source` and the
17
+ * component styles with it.
18
+ *
19
+ * Nothing here reads a file or touches the DOM. The caller supplies the two
20
+ * stylesheets as text, because that is the only part that differs between a
21
+ * Vitest run, a Node script and a CI step.
22
+ */
23
+ /** A problem found in an app's stylesheet, written to be read in a failure. */
24
+ export type StylingProblem = {
25
+ /** What is wrong, in one sentence. */
26
+ message: string;
27
+ /** The line to add, where there is a single obvious one. */
28
+ fix?: string;
29
+ };
30
+ export type StylingInput = {
31
+ /** The app's own stylesheet — the file that imports Tailwind. */
32
+ css: string;
33
+ /** `node_modules/rei-kit/dist/tokens.css`, for the roles it declares. */
34
+ tokens: string;
35
+ };
36
+ /**
37
+ * What is missing from an app's stylesheet, as a list to assert is empty.
38
+ *
39
+ * ```ts
40
+ * import { checkStyling } from 'rei-kit/check'
41
+ *
42
+ * it('is wired to the kit', () => {
43
+ * expect(
44
+ * checkStyling({
45
+ * css: readFileSync('src/assets/main.css', 'utf8'),
46
+ * tokens: readFileSync('node_modules/rei-kit/dist/tokens.css', 'utf8'),
47
+ * }),
48
+ * ).toEqual([])
49
+ * })
50
+ * ```
51
+ */
52
+ export declare function checkStyling({ css, tokens }: StylingInput): StylingProblem[];
package/dist/check.js ADDED
@@ -0,0 +1,55 @@
1
+ //#region src/check/index.ts
2
+ /** Every `--color-<name>` a stylesheet declares. */
3
+ function colourRoles(css) {
4
+ return new Set([...css.matchAll(/--color-([a-z0-9-]+)\s*:/g)].map(([, name]) => name));
5
+ }
6
+ function imports(css, file) {
7
+ return new RegExp(`@import\\s+['"]rei-kit/${file}['"]`).test(css);
8
+ }
9
+ /**
10
+ * What is missing from an app's stylesheet, as a list to assert is empty.
11
+ *
12
+ * ```ts
13
+ * import { checkStyling } from 'rei-kit/check'
14
+ *
15
+ * it('is wired to the kit', () => {
16
+ * expect(
17
+ * checkStyling({
18
+ * css: readFileSync('src/assets/main.css', 'utf8'),
19
+ * tokens: readFileSync('node_modules/rei-kit/dist/tokens.css', 'utf8'),
20
+ * }),
21
+ * ).toEqual([])
22
+ * })
23
+ * ```
24
+ */
25
+ function checkStyling({ css, tokens }) {
26
+ const problems = [];
27
+ const preset = imports(css, "mobile.css") || imports(css, "web.css");
28
+ if (preset && imports(css, "mobile.css") && imports(css, "web.css")) problems.push({
29
+ message: "Both presets are imported. They are two answers to the same question, and the second one wins wherever they disagree.",
30
+ fix: "keep one of @import 'rei-kit/mobile.css' or @import 'rei-kit/web.css'"
31
+ });
32
+ if (!preset) {
33
+ if (!imports(css, "styles.css")) problems.push({
34
+ message: "The compiled component styles are not imported, so every component keeps its markup and loses its layout. Nothing else reports this: the build is green and the page renders.",
35
+ fix: "@import 'rei-kit/mobile.css'; /* or web.css — the preset carries the rest too */"
36
+ });
37
+ if (!/@source\s+['"][^'"]*node_modules\/rei-kit[^'"]*['"]/.test(css)) problems.push({
38
+ message: "Tailwind is not told to scan the kit, so it emits no utility the components ask for. It does not walk node_modules unless pointed at it.",
39
+ fix: "@source '<relative path>/node_modules/rei-kit/dist';"
40
+ });
41
+ }
42
+ const declared = colourRoles(css);
43
+ if (!preset && !imports(css, "tokens.css")) {
44
+ const missing = [...colourRoles(tokens)].filter((role) => !declared.has(role));
45
+ if (missing.length) problems.push({
46
+ message: `These colour roles are never defined, so every utility built on them emits nothing: ${missing.join(", ")}.`,
47
+ fix: "@import 'rei-kit/tokens.css';"
48
+ });
49
+ }
50
+ return problems;
51
+ }
52
+ //#endregion
53
+ export { checkStyling };
54
+
55
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","names":[],"sources":["../src/check/index.ts"],"sourcesContent":["/**\n * The wiring that fails silently, checked at unit-test speed.\n *\n * Every line of this package's install can be left out and leave a build that\n * is green: a missing `@source` means Tailwind never emits the utilities the\n * components ask for, a missing stylesheet import means the components keep\n * their markup and lose their layout, and a colour role the app never defines\n * makes `bg-primary` emit no declaration at all. None of it is visible to\n * `vue-tsc`, to a component test, or to a reader of the diff. One of the apps\n * in this family shipped a release with its tab bar invisible exactly this\n * way.\n *\n * Both apps then wrote the same check, independently, with three of the four\n * assertions carrying the same names — which is this kit's own test for a\n * missing part. So the check moved here, and it knows one thing their copies\n * could not: that the preset exists and carries the `@source` and the\n * component styles with it.\n *\n * Nothing here reads a file or touches the DOM. The caller supplies the two\n * stylesheets as text, because that is the only part that differs between a\n * Vitest run, a Node script and a CI step.\n */\n\n/** A problem found in an app's stylesheet, written to be read in a failure. */\nexport type StylingProblem = {\n /** What is wrong, in one sentence. */\n message: string\n /** The line to add, where there is a single obvious one. */\n fix?: string\n}\n\nexport type StylingInput = {\n /** The app's own stylesheet — the file that imports Tailwind. */\n css: string\n /** `node_modules/rei-kit/dist/tokens.css`, for the roles it declares. */\n tokens: string\n}\n\n/** Every `--color-<name>` a stylesheet declares. */\nfunction colourRoles(css: string): Set<string> {\n return new Set([...css.matchAll(/--color-([a-z0-9-]+)\\s*:/g)].map(([, name]) => name!))\n}\n\nfunction imports(css: string, file: string): boolean {\n return new RegExp(`@import\\\\s+['\"]rei-kit/${file}['\"]`).test(css)\n}\n\n/**\n * What is missing from an app's stylesheet, as a list to assert is empty.\n *\n * ```ts\n * import { checkStyling } from 'rei-kit/check'\n *\n * it('is wired to the kit', () => {\n * expect(\n * checkStyling({\n * css: readFileSync('src/assets/main.css', 'utf8'),\n * tokens: readFileSync('node_modules/rei-kit/dist/tokens.css', 'utf8'),\n * }),\n * ).toEqual([])\n * })\n * ```\n */\nexport function checkStyling({ css, tokens }: StylingInput): StylingProblem[] {\n const problems: StylingProblem[] = []\n\n /* The preset is tokens, shell, materials, palettes, the compiled component\n styles and the `@source` — so an app that imports one has answered every\n question below at once, and asking them separately would report faults it\n does not have. */\n const preset = imports(css, 'mobile.css') || imports(css, 'web.css')\n\n if (preset && imports(css, 'mobile.css') && imports(css, 'web.css')) {\n problems.push({\n message:\n 'Both presets are imported. They are two answers to the same question, and the second one wins wherever they disagree.',\n fix: \"keep one of @import 'rei-kit/mobile.css' or @import 'rei-kit/web.css'\",\n })\n }\n\n if (!preset) {\n if (!imports(css, 'styles.css')) {\n problems.push({\n message:\n 'The compiled component styles are not imported, so every component keeps its markup and loses its layout. Nothing else reports this: the build is green and the page renders.',\n fix: \"@import 'rei-kit/mobile.css'; /* or web.css — the preset carries the rest too */\",\n })\n }\n\n if (!/@source\\s+['\"][^'\"]*node_modules\\/rei-kit[^'\"]*['\"]/.test(css)) {\n problems.push({\n message:\n 'Tailwind is not told to scan the kit, so it emits no utility the components ask for. It does not walk node_modules unless pointed at it.',\n fix: \"@source '<relative path>/node_modules/rei-kit/dist';\",\n })\n }\n }\n\n /* Checked last and only when the roles cannot be arriving from the kit\n itself, so the list reports what the app has to define rather than\n repeating the import it is already being told about. */\n const declared = colourRoles(css)\n if (!preset && !imports(css, 'tokens.css')) {\n const missing = [...colourRoles(tokens)].filter((role) => !declared.has(role))\n\n if (missing.length) {\n problems.push({\n message: `These colour roles are never defined, so every utility built on them emits nothing: ${missing.join(', ')}.`,\n fix: \"@import 'rei-kit/tokens.css';\",\n })\n }\n }\n\n return problems\n}\n"],"mappings":";;AAuCA,SAAS,YAAY,KAA0B;CAC7C,OAAO,IAAI,IAAI,CAAC,GAAG,IAAI,SAAS,2BAA2B,CAAC,CAAC,CAAC,KAAK,GAAG,UAAU,IAAK,CAAC;AACxF;AAEA,SAAS,QAAQ,KAAa,MAAuB;CACnD,OAAO,IAAI,OAAO,0BAA0B,KAAK,KAAK,CAAC,CAAC,KAAK,GAAG;AAClE;;;;;;;;;;;;;;;;;AAkBA,SAAgB,aAAa,EAAE,KAAK,UAA0C;CAC5E,MAAM,WAA6B,CAAC;CAMpC,MAAM,SAAS,QAAQ,KAAK,YAAY,KAAK,QAAQ,KAAK,SAAS;CAEnE,IAAI,UAAU,QAAQ,KAAK,YAAY,KAAK,QAAQ,KAAK,SAAS,GAChE,SAAS,KAAK;EACZ,SACE;EACF,KAAK;CACP,CAAC;CAGH,IAAI,CAAC,QAAQ;EACX,IAAI,CAAC,QAAQ,KAAK,YAAY,GAC5B,SAAS,KAAK;GACZ,SACE;GACF,KAAK;EACP,CAAC;EAGH,IAAI,CAAC,sDAAsD,KAAK,GAAG,GACjE,SAAS,KAAK;GACZ,SACE;GACF,KAAK;EACP,CAAC;CAEL;CAKA,MAAM,WAAW,YAAY,GAAG;CAChC,IAAI,CAAC,UAAU,CAAC,QAAQ,KAAK,YAAY,GAAG;EAC1C,MAAM,UAAU,CAAC,GAAG,YAAY,MAAM,CAAC,CAAC,CAAC,QAAQ,SAAS,CAAC,SAAS,IAAI,IAAI,CAAC;EAE7E,IAAI,QAAQ,QACV,SAAS,KAAK;GACZ,SAAS,uFAAuF,QAAQ,KAAK,IAAI,EAAE;GACnH,KAAK;EACP,CAAC;CAEL;CAEA,OAAO;AACT"}
@@ -47,7 +47,9 @@ declare const __VLS_export: <T extends string | number | undefined = string>(__V
47
47
  }> & (typeof globalThis extends {
48
48
  __VLS_PROPS_FALLBACK: infer P;
49
49
  } ? P : {});
50
- expose: (exposed: {}) => void;
50
+ expose: (exposed: import('vue').ShallowUnwrapRef<{
51
+ focus: () => void;
52
+ }>) => void;
51
53
  attrs: any;
52
54
  slots: {
53
55
  prefix?: () => unknown;
@@ -51,7 +51,9 @@ declare const __VLS_export: <T extends string | number>(__VLS_props: NonNullable
51
51
  }> & (typeof globalThis extends {
52
52
  __VLS_PROPS_FALLBACK: infer P;
53
53
  } ? P : {});
54
- expose: (exposed: {}) => void;
54
+ expose: (exposed: import('vue').ShallowUnwrapRef<{
55
+ focus: () => void;
56
+ }>) => void;
55
57
  attrs: any;
56
58
  slots: {};
57
59
  emit: (event: "update:modelValue", value: T | undefined) => void;
@@ -36,7 +36,22 @@ type __VLS_Props = {
36
36
  */
37
37
  fieldId?: string | undefined;
38
38
  };
39
- declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
39
+ /**
40
+ * Focus the control, for a caller that owns when it happens.
41
+ *
42
+ * A `ref` on a component gives the component and not the element, so without
43
+ * this a field cannot be focused at all — which is why an app that focuses
44
+ * its amount field when a sheet opens, and again when the amount is
45
+ * rejected, wrote the whole field by hand instead and said so in a comment.
46
+ * That is the gap test, with the reason already written down.
47
+ *
48
+ * `ErrorSummary` has exposed `focus` since it existed, for the same need
49
+ * from the other end.
50
+ */
51
+ declare function focus(): void;
52
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {
53
+ focus: typeof focus;
54
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
40
55
  "update:modelValue": (value: string) => any;
41
56
  }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
42
57
  "onUpdate:modelValue"?: (value: string) => any;
@@ -52,7 +52,22 @@ type __VLS_Props = {
52
52
  fieldId?: string | undefined;
53
53
  size?: 'sm' | 'md' | undefined;
54
54
  } & /* @vue-ignore */ Omit<InputHTMLAttributes, 'size' | 'type'>;
55
- declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
55
+ /**
56
+ * Focus the control, for a caller that owns when it happens.
57
+ *
58
+ * A `ref` on a component gives the component and not the element, so without
59
+ * this a field cannot be focused at all — which is why an app that focuses
60
+ * its amount field when a sheet opens, and again when the amount is
61
+ * rejected, wrote the whole field by hand instead and said so in a comment.
62
+ * That is the gap test, with the reason already written down.
63
+ *
64
+ * `ErrorSummary` has exposed `focus` since it existed, for the same need
65
+ * from the other end.
66
+ */
67
+ declare function focus(): void;
68
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {
69
+ focus: typeof focus;
70
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
56
71
  toggle: (visible: boolean) => any;
57
72
  "update:modelValue": (value: string) => any;
58
73
  }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { a as addDays, c as lastNDays, d as toDateKey, f as todayKey, i as needsIosInstall, l as leadingBlanks, n as isApplePortable, o as eachDayOfYear, r as isInstalled, s as fromDateKey, t as SettingsGroup_default, u as startOfWeek } from "./SettingsGroup-BXkajKGl.js";
2
2
  import { a as formatNumber, i as formatDate, o as setFormatLocale, r as watchVisibility } from "./environment-Cz5KiC1t.js";
3
3
  import { a as BaseCheckbox_default, c as useBoundValue, d as ensureSheetRoot, i as textDirection, l as useVisualViewport, n as elementDirection, o as BaseSheet_default, r as horizontalStep, t as focusTarget, u as SHEET_ROOT_ID } from "./focus-target-BtcoJdmz.js";
4
- import { _ as toRedirectPath, a as useFieldAttrs, c as useToast, d as isThemePreference, f as readStoredTheme, g as safeRedirect, h as tapFeedback, i as BaseInput_default, l as useOnline, m as useTheme, n as useAnnounce, o as FormField_default, p as setThemeStorageKey, r as GoogleButton_default, s as BaseAlert_default, t as announce, u as applyTheme } from "./use-announce-D8SKsiqn.js";
4
+ import { _ as toRedirectPath, a as useFieldAttrs, c as useToast, d as isThemePreference, f as readStoredTheme, g as safeRedirect, h as tapFeedback, i as BaseInput_default, l as useOnline, m as useTheme, n as useAnnounce, o as FormField_default, p as setThemeStorageKey, r as GoogleButton_default, s as BaseAlert_default, t as announce, u as applyTheme } from "./use-announce-BGZnV78W.js";
5
5
  import { n as registerErrorMapper, r as toAppError, t as AppError } from "./app-error-DF9cijE0.js";
6
6
  import { a as BaseSkeleton_default, c as useMediaQuery, l as useDragScroll, n as ScrollArea_default, o as useMenuKeys, s as useAnchoredPanel, t as BaseListbox_default } from "./BaseListbox-D-NQ6nDd.js";
7
7
  import { t as _plugin_vue_export_helper_default } from "./_plugin-vue_export-helper-BOaGB7Aw.js";
@@ -1021,12 +1021,29 @@ var BaseSelect_default = /* @__PURE__ */ defineComponent({
1021
1021
  "modelModifiers": {}
1022
1022
  }),
1023
1023
  emits: ["update:modelValue"],
1024
- setup(__props) {
1024
+ setup(__props, { expose: __expose }) {
1025
1025
  const SIZE_CLASS = {
1026
1026
  sm: "h-11 text-sm",
1027
1027
  md: "h-11 text-base"
1028
1028
  };
1029
1029
  const model = useModel(__props, "modelValue");
1030
+ const control = ref(null);
1031
+ /**
1032
+ * Focus the control, for a caller that owns when it happens.
1033
+ *
1034
+ * A `ref` on a component gives the component and not the element, so without
1035
+ * this a field cannot be focused at all — which is why an app that focuses
1036
+ * its amount field when a sheet opens, and again when the amount is
1037
+ * rejected, wrote the whole field by hand instead and said so in a comment.
1038
+ * That is the gap test, with the reason already written down.
1039
+ *
1040
+ * `ErrorSummary` has exposed `focus` since it existed, for the same need
1041
+ * from the other end.
1042
+ */
1043
+ function focus() {
1044
+ control.value?.focus();
1045
+ }
1046
+ __expose({ focus });
1030
1047
  return (_ctx, _cache) => {
1031
1048
  return openBlock(), createBlock(FormField_default, {
1032
1049
  "field-id": __props.fieldId,
@@ -1038,6 +1055,8 @@ var BaseSelect_default = /* @__PURE__ */ defineComponent({
1038
1055
  }, {
1039
1056
  default: withCtx(({ id, describedBy, invalid }) => [createElementVNode("div", _hoisted_1$47, [withDirectives(createElementVNode("select", {
1040
1057
  id,
1058
+ ref_key: "control",
1059
+ ref: control,
1041
1060
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => model.value = $event),
1042
1061
  "aria-invalid": invalid,
1043
1062
  "aria-describedby": describedBy,
@@ -1605,10 +1624,27 @@ var BaseTextarea_default = /* @__PURE__ */ defineComponent({
1605
1624
  fieldId: { default: () => void 0 }
1606
1625
  },
1607
1626
  emits: ["update:modelValue"],
1608
- setup(__props, { emit: __emit }) {
1627
+ setup(__props, { expose: __expose, emit: __emit }) {
1609
1628
  const { fieldClass, fieldStyle, controlAttrs } = useFieldAttrs();
1610
1629
  const emit = __emit;
1611
1630
  const model = useBoundValue(() => __props.modelValue, (value) => emit("update:modelValue", value));
1631
+ const control = ref(null);
1632
+ /**
1633
+ * Focus the control, for a caller that owns when it happens.
1634
+ *
1635
+ * A `ref` on a component gives the component and not the element, so without
1636
+ * this a field cannot be focused at all — which is why an app that focuses
1637
+ * its amount field when a sheet opens, and again when the amount is
1638
+ * rejected, wrote the whole field by hand instead and said so in a comment.
1639
+ * That is the gap test, with the reason already written down.
1640
+ *
1641
+ * `ErrorSummary` has exposed `focus` since it existed, for the same need
1642
+ * from the other end.
1643
+ */
1644
+ function focus() {
1645
+ control.value?.focus();
1646
+ }
1647
+ __expose({ focus });
1612
1648
  return (_ctx, _cache) => {
1613
1649
  return openBlock(), createBlock(FormField_default, {
1614
1650
  "field-id": __props.fieldId,
@@ -1622,6 +1658,8 @@ var BaseTextarea_default = /* @__PURE__ */ defineComponent({
1622
1658
  }, {
1623
1659
  default: withCtx(({ id, describedBy, invalid }) => [withDirectives(createElementVNode("textarea", mergeProps({
1624
1660
  id,
1661
+ ref_key: "control",
1662
+ ref: control,
1625
1663
  "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isRef(model) ? model.value = $event : null),
1626
1664
  rows: __props.rows,
1627
1665
  "aria-invalid": invalid,
@@ -4728,7 +4766,7 @@ var PasswordInput_default = /* @__PURE__ */ defineComponent({
4728
4766
  size: { default: "md" }
4729
4767
  },
4730
4768
  emits: ["update:modelValue", "toggle"],
4731
- setup(__props, { emit: __emit }) {
4769
+ setup(__props, { expose: __expose, emit: __emit }) {
4732
4770
  const { fieldClass, fieldStyle, controlAttrs } = useFieldAttrs();
4733
4771
  /**
4734
4772
  * A password field you can look at.
@@ -4772,6 +4810,23 @@ var PasswordInput_default = /* @__PURE__ */ defineComponent({
4772
4810
  visible.value = !visible.value;
4773
4811
  emit("toggle", visible.value);
4774
4812
  }
4813
+ const control = ref(null);
4814
+ /**
4815
+ * Focus the control, for a caller that owns when it happens.
4816
+ *
4817
+ * A `ref` on a component gives the component and not the element, so without
4818
+ * this a field cannot be focused at all — which is why an app that focuses
4819
+ * its amount field when a sheet opens, and again when the amount is
4820
+ * rejected, wrote the whole field by hand instead and said so in a comment.
4821
+ * That is the gap test, with the reason already written down.
4822
+ *
4823
+ * `ErrorSummary` has exposed `focus` since it existed, for the same need
4824
+ * from the other end.
4825
+ */
4826
+ function focus() {
4827
+ control.value?.focus();
4828
+ }
4829
+ __expose({ focus });
4775
4830
  return (_ctx, _cache) => {
4776
4831
  return openBlock(), createBlock(FormField_default, {
4777
4832
  class: normalizeClass(unref(fieldClass)),
@@ -4785,6 +4840,8 @@ var PasswordInput_default = /* @__PURE__ */ defineComponent({
4785
4840
  }, {
4786
4841
  default: withCtx(({ id, describedBy, invalid }) => [createElementVNode("div", _hoisted_1$2, [createElementVNode("input", mergeProps({
4787
4842
  id,
4843
+ ref_key: "control",
4844
+ ref: control,
4788
4845
  type: visible.value ? "text" : "password",
4789
4846
  value: __props.modelValue,
4790
4847
  "aria-invalid": invalid,
@@ -5132,7 +5189,7 @@ function createI18nRuntime(options) {
5132
5189
  *
5133
5190
  * The fallback keeps `vitest` and `vite dev` honest, where no define runs.
5134
5191
  */
5135
- var VERSION = "3.3.0";
5192
+ var VERSION = "3.5.0";
5136
5193
  //#endregion
5137
5194
  export { ActivityGrid_default as ActivityGrid, AnnounceHost_default as AnnounceHost, AppError, AvatarStack_default as AvatarStack, BarChart_default as BarChart, BaseAlert_default as BaseAlert, BaseAvatar_default as BaseAvatar, BaseBadge_default as BaseBadge, BaseButton_default as BaseButton, BaseCalendar_default as BaseCalendar, BaseCard_default as BaseCard, BaseCheckbox_default as BaseCheckbox, BaseChip_default as BaseChip, BaseCombobox_default as BaseCombobox, BaseDatePicker_default as BaseDatePicker, BaseInput_default as BaseInput, BaseKbd_default as BaseKbd, BaseLink_default as BaseLink, BaseListbox_default as BaseListbox, BaseMenu_default as BaseMenu, BasePopconfirm_default as BasePopconfirm, BasePopover_default as BasePopover, BaseRadioGroup_default as BaseRadioGroup, BaseRating_default as BaseRating, BaseSelect_default as BaseSelect, BaseSeparator_default as BaseSeparator, BaseSheet_default as BaseSheet, BaseSkeleton_default as BaseSkeleton, BaseSlider_default as BaseSlider, BaseSpinner_default as BaseSpinner, BaseStepper_default as BaseStepper, BaseSwitch_default as BaseSwitch, BaseTable_default as BaseTable, BaseTextarea_default as BaseTextarea, BaseTimeline_default as BaseTimeline, CircularProgress_default as CircularProgress, CodeBlock_default as CodeBlock, ColorPicker_default as ColorPicker, CopyButton_default as CopyButton, DescriptionList_default as DescriptionList, DonutChart_default as DonutChart, EmptyState_default as EmptyState, ErrorBoundary_default as ErrorBoundary, ErrorSummary_default as ErrorSummary, FileDrop_default as FileDrop, FormField_default as FormField, GoogleButton_default as GoogleButton, LocaleLinks_default as LocaleLinks, MATERIALS, NumberInput_default as NumberInput, PALETTES, PageContainer_default as PageContainer, PageHeader_default as PageHeader, PasswordInput_default as PasswordInput, PinInput_default as PinInput, PriceCard_default as PriceCard, ProgressBar_default as ProgressBar, SHEET_ROOT_ID, ScrollArea_default as ScrollArea, SectionHeading_default as SectionHeading, SegmentedControl_default as SegmentedControl, SettingsGroup_default as SettingsGroup, SettingsRow_default as SettingsRow, SkeletonList_default as SkeletonList, SliderField_default as SliderField, StatCard_default as StatCard, TabBar_default as TabBar, TagsInput_default as TagsInput, TimePicker_default as TimePicker, ToastHost_default as ToastHost, ToggleGroup_default as ToggleGroup, ToneDot_default as ToneDot, VERSION, VirtualList_default as VirtualList, addDays, announce, applyMaterial, applyPalette, applyTheme, createI18nRuntime, downloadJson, eachDayOfYear, elementDirection, ensureSheetRoot, formatDate, formatNumber, fromDateKey, horizontalStep, isApplePortable, isInstalled, isMaterial, isPaletteName, isThemePreference, lastNDays, leadingBlanks, needsIosInstall, readStoredTheme, registerErrorMapper, relativeDayLabel, safeRedirect, setFormatLocale, setMaterialStorageKey, setPaletteStorageKey, setThemeStorageKey, startOfWeek, tapFeedback, textDirection, toAppError, toDateKey, toRedirectPath, todayKey, useAnnounce, useDebouncedCallback, useDragScroll, useMaterial, useMediaQuery, useOnline, usePalette, useTheme, useToast, useToday, useVisualViewport };
5138
5195