@omnitend/dashboard-for-laravel 0.46.0 → 0.47.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.
@@ -215,6 +215,19 @@ export interface FieldDefinition {
215
215
  * `FormFieldDefinition` re-declares this as required for inference.)
216
216
  */
217
217
  default?: any;
218
+ /**
219
+ * For a field whose value is a list of rows (a `repeater`, or a span
220
+ * field that renders its own rows and owns `key.N.*` error keys): the
221
+ * row's own name, called with the row (`model[key][index]`, or `{}` when
222
+ * the model has no such row) and its 0-based index. When it returns a
223
+ * non-empty string, the error summary lists that row's errors under it
224
+ * alone ("Chaucer Ale (Pint): Enter a price.") instead of
225
+ * "<sub-field label> (line N)". Returning `undefined`, `null` or `""`
226
+ * (a row with no name yet), or throwing, keeps the line-number label.
227
+ * Only labels: which field owns the error, and what a click on the
228
+ * summary row focuses, are unchanged.
229
+ */
230
+ rowLabel?: (row: Record<string, any>, index: number) => string | null | undefined;
218
231
  /** Label for a repeater's "add row" button (default: "Add"). */
219
232
  addLabel?: string;
220
233
  /** Minimum / maximum number of repeater rows. */
@@ -295,6 +308,10 @@ export interface FieldDefinition {
295
308
  * every `editFields` key, so those decorative fields are POSTed alongside
296
309
  * the real ones (an empty string, an empty array) purely because they were
297
310
  * declared.
311
+ *
312
+ * Applies per KEY (#228): DXTable drops a key only when no field with that
313
+ * key is both submitting and visible, so a `submit: false` display twin
314
+ * does not strip the value of a visible editable field sharing its key.
298
315
  */
299
316
  submit?: boolean;
300
317
  /**
@@ -342,6 +359,8 @@ export interface BaseFieldDef {
342
359
  plaintext?: MaybeFn<boolean>;
343
360
  submit?: boolean;
344
361
  errorKeys?: string[];
362
+ /** On a repeater, or a span field that renders its own rows. */
363
+ rowLabel?: (row: Record<string, any>, index: number) => string | null | undefined;
345
364
  when?: MaybeFn<boolean>;
346
365
  show?: () => boolean;
347
366
  }
@@ -488,6 +507,51 @@ export interface FormTab {
488
507
  /** Lazily mount tab content until first activated */
489
508
  lazy?: boolean;
490
509
  }
510
+ /**
511
+ * Slot props of DXField's `password-actions` slot (DXForm:
512
+ * `password-actions(<key>)`): content placed beside a password input, such as
513
+ * a "Generate password" button. It renders after the input group (the input
514
+ * and the reveal (eye) toggle), in `.dx-password-field__actions`, and wraps
515
+ * onto its own line below the input when the row is too narrow to keep
516
+ * `--dx-password-input-min-width`. `setRevealed` drives the same state the
517
+ * eye toggles.
518
+ *
519
+ * ```vue
520
+ * <template #password-actions(password)="{ update, setRevealed, disabled }">
521
+ * <DButton variant="secondary" :disabled="disabled"
522
+ * @click="update(generatePassword()); setRevealed(true)">Generate</DButton>
523
+ * </template>
524
+ * ```
525
+ */
526
+ export interface PasswordActionsSlotProps {
527
+ /** The field definition being rendered. */
528
+ field: FieldDefinition;
529
+ /** The model passed to field predicates (defaults to the live form data). */
530
+ model: any;
531
+ /** The current field value. */
532
+ value: any;
533
+ /** Write a new value (also marks the field touched and clears its error). */
534
+ update: (value: any) => void;
535
+ /** Whether the password is currently shown as plain text. */
536
+ revealed: boolean;
537
+ /**
538
+ * Show (`true`) or mask (`false`) the password, exactly as the eye does.
539
+ * A no-op on a `revealable: false` field, which never unmasks.
540
+ */
541
+ setRevealed: (revealed: boolean) => void;
542
+ /** Whether the field is disabled or read-only. */
543
+ disabled: boolean;
544
+ }
545
+ /**
546
+ * Slot props of DXTable's `edit-password-actions(<key>)` slot, the edit/create
547
+ * modal's form of {@link PasswordActionsSlotProps}. `item` is the row being
548
+ * edited, `null` in create mode. (`model` is not passed, as with the modal's
549
+ * other field slots.)
550
+ */
551
+ export interface EditPasswordActionsSlotProps extends Omit<PasswordActionsSlotProps, "model"> {
552
+ /** The row being edited; `null` in create mode. */
553
+ item: any;
554
+ }
491
555
  /**
492
556
  * The theme's extra colour variant, `pending`: waiting, and the next move is
493
557
  * not yours ("awaiting payment", "sent to printer, not yet confirmed").
@@ -1,18 +1,17 @@
1
- /**
2
- * Which field a validation-error key belongs to (#194).
3
- *
4
- * One pure function decides, so the error summary's rows, the tab a failed
5
- * submit selects and the field it scrolls to can never disagree. No Vue: the
6
- * caller injects visibility and label resolution, so DXForm can pass its own
7
- * `when`/`context`-aware predicates and a standalone summary can use the
8
- * defaults below.
9
- */
10
1
  import type { FieldDefinition, FormTab } from "../types";
11
- import type { ValidationErrors } from "../composables/useForm";
2
+ import type { FailedRow, ValidationErrors } from "../composables/useForm";
12
3
  /** One error key and where it belongs. */
13
4
  export interface ErrorTarget {
14
5
  /** The key as the server sent it (`lines.0.price`). */
15
6
  errorKey: string;
7
+ /**
8
+ * Where to take the user for this error now. The same as `errorKey`,
9
+ * except for a row error resolved with `failedRows`: the key at the
10
+ * failed row's CURRENT index (`lines.1.price` once row 0 is removed),
11
+ * or the owning field's key when that row is gone. Always set by
12
+ * `resolveErrorTargets`; optional so targets built by hand still type.
13
+ */
14
+ focusKey?: string;
16
15
  /** The server's messages for that key, as sent. */
17
16
  messages: string[];
18
17
  /**
@@ -25,7 +24,10 @@ export interface ErrorTarget {
25
24
  fieldKey: string | null;
26
25
  /** The tab holding the owning field, or `null` (flat form, or unowned). */
27
26
  tabKey: string | null;
28
- /** A readable name for the key: "Price (line 1)", "Delivery date". */
27
+ /**
28
+ * A readable name for the key: "Price (line 1)", "Delivery date", or a
29
+ * row's own name from the field's `rowLabel`.
30
+ */
29
31
  label: string;
30
32
  }
31
33
  export interface ResolveErrorTargetsOptions {
@@ -52,6 +54,14 @@ export interface ResolveErrorTargetsOptions {
52
54
  * humanised key, so a broken label can never hide an error.
53
55
  */
54
56
  resolveLabel?: (field: FieldDefinition, labelModel: Record<string, any>) => string | null | undefined;
57
+ /**
58
+ * The rows a failed submit's errors named, as captured then
59
+ * (`SubmitFailure.failedRows`). Pass it when resolving that failure's
60
+ * errors after the form may have changed (the error summary does), so a
61
+ * row error keeps the name of the row that failed and points at where
62
+ * that row is now. Leave it out for the form's live errors.
63
+ */
64
+ failedRows?: Record<string, FailedRow>;
55
65
  }
56
66
  /**
57
67
  * `delivery_date` → "Delivery date"; `lines.0.price` → "Lines price (line 1)".
@@ -75,7 +85,11 @@ export declare function humaniseErrorKey(key: string): string;
75
85
  *
76
86
  * Labels: the owning field's label; for `field.N.sub` the sub-field's label
77
87
  * (when the field defines `fields` and one has that key) or the field's own,
78
- * plus "(line N+1)"; for any other nested key (a media map's
88
+ * plus "(line N+1)" — unless the field's `rowLabel` names that row, when
89
+ * the row's name is the whole label. With `failedRows`, a row key's label
90
+ * reads the row as it was when the submit failed, and its `focusKey` and
91
+ * line number follow that row to where it is now (see `ownedTarget`); for
92
+ * any other nested key (a media map's
79
93
  * `image_media.<uuid>`) the field's label. An unowned key is humanised.
80
94
  *
81
95
  * Display lines: "Label: message", except that the label is left off when
@@ -57,3 +57,19 @@ export declare function isFieldVisible(field: {
57
57
  export declare function isSubmittableField(field: {
58
58
  submit?: boolean;
59
59
  }): boolean;
60
+ /**
61
+ * The payload keys to drop on submit: every field key for which NO field with
62
+ * that key is both submittable (`submit !== false`) and visible (#228).
63
+ *
64
+ * Decided per KEY, across all the fields that share it, never per field. Two
65
+ * fields may share a key: an editable select plus a read-only display twin
66
+ * (`submit: false`) that shows instead for system-created rows. Stripping a
67
+ * key because ONE of its fields is presentational or hidden removed it from
68
+ * every save, including while the select was the visible field in use. A key
69
+ * whose fields are all presentational (#110) or all hidden (#117) is still
70
+ * dropped.
71
+ */
72
+ export declare function nonSubmittedFieldKeys<TField extends {
73
+ key: string;
74
+ submit?: boolean;
75
+ }>(fields: readonly TField[], isVisible: (field: TField) => boolean): Set<string>;
@@ -1,8 +1,8 @@
1
1
  {
2
- "generated": "2026-10-15T11:16:01.160Z",
2
+ "generated": "2026-10-21T13:01:22.201Z",
3
3
  "package": {
4
4
  "name": "@omnitend/dashboard-for-laravel",
5
- "version": "0.46.0"
5
+ "version": "0.47.1"
6
6
  },
7
7
  "components": {
8
8
  "base": [
@@ -2118,7 +2118,7 @@
2118
2118
  "name": "DXField",
2119
2119
  "category": "extended",
2120
2120
  "filePath": "resources/js/components/extended/DXField.vue",
2121
- "description": "Renders a single `FieldDefinition` of any type (text, select, autocomplete, checkbox, switch, repeater, currency, percentage, file/image, component, etc.) with its label, validation error, hint and help. Used by `DXForm` and `DXTable`'s edit modal; exposes `value`, `span`, `info`, `info-popover`, `hint` and `repeater-row` slots for per-field customisation. Structure (#135): a thin DISPATCHER. The shared chrome (label + validation feedback + hint + help + info) lives in `DXFieldShell`; the numeric controls (currency/percentage/number) in `DXNumericField`; the choice controls (select/searchable/radio/checkbox-group) in `DXChoiceField`; and the async option loading in the `useAsyncOptions` composable. This file decides which control to render inside the shell by `field.type`. None of those pieces are exported — they exist only to keep this component factored.",
2121
+ "description": "Renders a single `FieldDefinition` of any type (text, select, autocomplete, checkbox, switch, repeater, currency, percentage, file/image, component, etc.) with its label, validation error, hint and help. Used by `DXForm` and `DXTable`'s edit modal; exposes `value`, `span`, `info`, `info-popover`, `hint`, `repeater-row` and `password-actions` slots for per-field customisation. Structure (#135): a thin DISPATCHER. The shared chrome (label + validation feedback + hint + help + info) lives in `DXFieldShell`; the numeric controls (currency/percentage/number) in `DXNumericField`; the choice controls (select/searchable/radio/checkbox-group) in `DXChoiceField`; and the async option loading in the `useAsyncOptions` composable. This file decides which control to render inside the shell by `field.type`. None of those pieces are exported — they exist only to keep this component factored.",
2122
2122
  "props": [
2123
2123
  {
2124
2124
  "name": "field",
@@ -2205,7 +2205,7 @@
2205
2205
  "name": "(value: any) => void"
2206
2206
  },
2207
2207
  "name": "update",
2208
- "description": "Setter that writes the value back and clears the field's validation error."
2208
+ "description": "Setter that writes the value back and clears the field's validation error, and any error under `<key>.` (rows the slot draws itself)."
2209
2209
  }
2210
2210
  ]
2211
2211
  },
@@ -2287,7 +2287,7 @@
2287
2287
  "name": "(value: any) => void"
2288
2288
  },
2289
2289
  "name": "update",
2290
- "description": "Setter that writes the value back and clears the field's validation error."
2290
+ "description": "Setter that writes the value back and clears the field's validation error, and any error under `<key>.` (rows the slot draws itself)."
2291
2291
  }
2292
2292
  ]
2293
2293
  },
@@ -2317,6 +2317,64 @@
2317
2317
  "name": "repeater-row",
2318
2318
  "description": "Custom layout for a single repeater row, forwarded to `DXRepeater`'s `row` slot with its row props (row index, item, remove handler, etc.).",
2319
2319
  "bindings": []
2320
+ },
2321
+ {
2322
+ "name": "password-actions",
2323
+ "description": "Extra controls beside a password input, after its input group (the input and the reveal (eye) toggle), e.g. a \"Generate password\" button. They sit on the input's row while it keeps `--dx-password-input-min-width`, and wrap below it when the row is too narrow. Use an ordinary button (a `secondary` `DButton` matches the form's other buttons). Not rendered on a `plaintext` field.",
2324
+ "bindings": [
2325
+ {
2326
+ "title": "binding",
2327
+ "type": {
2328
+ "name": "FieldDefinition"
2329
+ },
2330
+ "name": "field",
2331
+ "description": "The field definition being rendered."
2332
+ },
2333
+ {
2334
+ "title": "binding",
2335
+ "type": {
2336
+ "name": "any"
2337
+ },
2338
+ "name": "model",
2339
+ "description": "The model passed to field predicates (defaults to the live form data)."
2340
+ },
2341
+ {
2342
+ "title": "binding",
2343
+ "type": {
2344
+ "name": "any"
2345
+ },
2346
+ "name": "value",
2347
+ "description": "The current field value."
2348
+ },
2349
+ {
2350
+ "title": "binding",
2351
+ "type": {
2352
+ "name": "(value: any) => void"
2353
+ },
2354
+ "name": "update",
2355
+ "description": "Setter that writes the value back and clears the field's validation error."
2356
+ },
2357
+ {
2358
+ "title": "binding",
2359
+ "type": {
2360
+ "name": "boolean"
2361
+ },
2362
+ "name": "revealed",
2363
+ "description": "Whether the password is currently shown as plain text."
2364
+ },
2365
+ {
2366
+ "name": "set-revealed",
2367
+ "title": "binding"
2368
+ },
2369
+ {
2370
+ "title": "binding",
2371
+ "type": {
2372
+ "name": "boolean"
2373
+ },
2374
+ "name": "disabled",
2375
+ "description": "Whether the field is disabled or read-only, so actions that change the value can disable themselves."
2376
+ }
2377
+ ]
2320
2378
  }
2321
2379
  ],
2322
2380
  "methods": []
@@ -2796,7 +2854,7 @@
2796
2854
  "name": "DXFormField",
2797
2855
  "category": "extended",
2798
2856
  "filePath": "resources/js/components/extended/DXFormField.vue",
2799
- "description": "DXFormField — internal per-field renderer for DXForm. Owns the single per-field render block that DXForm's tabbed and flat layouts both need: the `field(<key>)` full-replacement slot, the `field-before(<key>)`/`field-after(<key>)` wrapper slots, and the `<DXField>` element with its `value`/`span`/`info`/`hint`/`repeater-row` slot forwarding. Extracted so those per-field props/slots are wired in ONE place — before this, DXForm carried two near-identical copies (tabbed + flat) and a new per-field prop had to be added to both, which was easy to miss (see #78/#83). DXForm forwards all of its slots into each instance; this component only reads the ones matching its field's key. Internal: not exported from the package index — consumers use DXForm.",
2857
+ "description": "DXFormField — internal per-field renderer for DXForm. Owns the single per-field render block that DXForm's tabbed and flat layouts both need: the `field(<key>)` full-replacement slot, the `field-before(<key>)`/`field-after(<key>)` wrapper slots, and the `<DXField>` element with its `value`/`span`/`info`/`hint`/`repeater-row`/ `switch-list-item`/`password-actions` slot forwarding. Extracted so those per-field props/slots are wired in ONE place — before this, DXForm carried two near-identical copies (tabbed + flat) and a new per-field prop had to be added to both, which was easy to miss (see #78/#83). DXForm forwards all of its slots into each instance; this component only reads the ones matching its field's key. Internal: not exported from the package index — consumers use DXForm.",
2800
2858
  "props": [
2801
2859
  {
2802
2860
  "name": "field",
@@ -4126,7 +4184,7 @@
4126
4184
  "name": "DXTableEditorModal",
4127
4185
  "category": "extended",
4128
4186
  "filePath": "resources/js/components/extended/DXTableEditorModal.vue",
4129
- "description": "Internal edit/create modal for `DXTable` (#129). Renders the `DModal` + `DXForm` and maps DXTable's `edit-value`/`edit-span`/`tab-*` slots onto DXForm's `value`/`span`/`tab-*` slots, providing the row context and a `close` handle. Extracted so `DXTable` is a thin façade over the table render, the pagination, the editor logic (`useResourceEditor`) and this modal — rather than owning all four. The edit-modal slots reach here forwarded from DXTable (consumer → DXTable → here → DXForm). This component computes which keyed slots the consumer actually provided from its OWN `$slots`, so the slot-plumbing lives entirely with the modal, not the composable.",
4187
+ "description": "Internal edit/create modal for `DXTable` (#129). Renders the `DModal` + `DXForm` and maps DXTable's `edit-value`/`edit-span`/`edit-password-actions`/ `tab-*` slots onto DXForm's `value`/`span`/`password-actions`/`tab-*` slots, providing the row context and a `close` handle. Extracted so `DXTable` is a thin façade over the table render, the pagination, the editor logic (`useResourceEditor`) and this modal — rather than owning all four. The edit-modal slots reach here forwarded from DXTable (consumer → DXTable → here → DXForm). This component computes which keyed slots the consumer actually provided from its OWN `$slots`, so the slot-plumbing lives entirely with the modal, not the composable.",
4130
4188
  "props": [
4131
4189
  {
4132
4190
  "name": "show",
@@ -4373,6 +4431,68 @@
4373
4431
  }
4374
4432
  ]
4375
4433
  },
4434
+ {
4435
+ "name": "`edit-password-actions(${key})`",
4436
+ "description": "Extra controls beside password field `<key>`'s input in the edit/create modal, after its input group (the input and the reveal (eye) toggle); wraps below the input when the row is too narrow — e.g. a \"Generate password\" button. Name it `edit-password-actions(<fieldKey>)`.",
4437
+ "bindings": [
4438
+ {
4439
+ "name": "name",
4440
+ "title": "binding"
4441
+ },
4442
+ {
4443
+ "title": "binding",
4444
+ "type": {
4445
+ "name": "object"
4446
+ },
4447
+ "name": "item",
4448
+ "description": "The row being edited (null in create mode)."
4449
+ },
4450
+ {
4451
+ "title": "binding",
4452
+ "type": {
4453
+ "name": "any"
4454
+ },
4455
+ "name": "value",
4456
+ "description": "The current field value."
4457
+ },
4458
+ {
4459
+ "title": "binding",
4460
+ "type": {
4461
+ "name": "Function"
4462
+ },
4463
+ "name": "update",
4464
+ "description": "Call with a new value to update the field."
4465
+ },
4466
+ {
4467
+ "title": "binding",
4468
+ "type": {
4469
+ "name": "boolean"
4470
+ },
4471
+ "name": "revealed",
4472
+ "description": "Whether the password is currently shown as plain text."
4473
+ },
4474
+ {
4475
+ "name": "set-revealed",
4476
+ "title": "binding"
4477
+ },
4478
+ {
4479
+ "title": "binding",
4480
+ "type": {
4481
+ "name": "boolean"
4482
+ },
4483
+ "name": "disabled",
4484
+ "description": "Whether the field is disabled or read-only."
4485
+ },
4486
+ {
4487
+ "title": "binding",
4488
+ "type": {
4489
+ "name": "object"
4490
+ },
4491
+ "name": "field",
4492
+ "description": "The field definition."
4493
+ }
4494
+ ]
4495
+ },
4376
4496
  {
4377
4497
  "name": "`tab-content(${key})`",
4378
4498
  "description": "Replaces the auto-rendered fields of edit-modal tab `<key>` with custom content. Name it `tab-content(<tabKey>)`.",
@@ -1,7 +1,7 @@
1
1
  # Documentation Map
2
2
 
3
3
  > Auto-generated hierarchical overview of all documentation
4
- > Last updated: 2026-10-15T11:16:01.216Z
4
+ > Last updated: 2026-10-21T13:01:22.256Z
5
5
 
6
6
  This file provides a complete map of all available documentation for AI agents and developers.
7
7
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omnitend/dashboard-for-laravel",
3
- "version": "0.46.0",
3
+ "version": "0.47.1",
4
4
  "description": "Vue 3 dashboard components for Laravel with Bootstrap Vue Next",
5
5
  "type": "module",
6
6
  "main": "./dist/dashboard-for-laravel.umd.cjs",
@@ -1644,6 +1644,81 @@ $dx-monospace-elements: "code, kbd, samp, pre";
1644
1644
  font-family: var(--dx-font-family-figures), var(--bs-font-monospace);
1645
1645
  }
1646
1646
 
1647
+ // ----------------------------------------------------------------------------
1648
+ // DXField password fields: the eye as part of the input, actions that wrap
1649
+ // ----------------------------------------------------------------------------
1650
+ //
1651
+ // The reveal (eye) toggle is drawn as part of the field: the input's border
1652
+ // colour, radius and background, a muted icon, and the input's own focus
1653
+ // treatment (navy border + halo). As a plain `outline-secondary` button it was
1654
+ // a darker, square-cornered box stuck to a light rounded input. Driven through
1655
+ // Bootstrap's `--bs-btn-*` variables, so hover/active/focus keep Bootstrap's
1656
+ // resolution order. `.btn.` lifts it over `.btn-outline-secondary`.
1657
+ //
1658
+ // A `password-actions` slot (a Generate button) sits AFTER the input group,
1659
+ // not in it, with a gap: it is an ordinary button beside the field rather than
1660
+ // a third piece of the control. The group asks for room for
1661
+ // `--dx-password-input-min-width` of input plus the square eye; when the row
1662
+ // cannot give the group that AND the actions, the actions wrap onto their own
1663
+ // line below it, so the input never shrinks to a couple of characters. The
1664
+ // group still has `min-width: 0`: in a container narrower than the minimum it
1665
+ // shrinks rather than overflowing.
1666
+ $dx-password-input-min-width: 11rem !default;
1667
+ $dx-password-actions-gap: 0.5rem !default;
1668
+
1669
+ :root {
1670
+ --dx-password-input-min-width: #{$dx-password-input-min-width};
1671
+ }
1672
+
1673
+ .btn.dx-password-reveal {
1674
+ --bs-btn-color: var(--bs-secondary-color);
1675
+ --bs-btn-bg: #{$input-bg};
1676
+ --bs-btn-border-color: var(--d-input-border-color);
1677
+ --bs-btn-border-radius: #{$input-border-radius};
1678
+ --bs-btn-hover-color: var(--bs-body-color);
1679
+ --bs-btn-hover-bg: var(--bs-tertiary-bg);
1680
+ --bs-btn-hover-border-color: var(--d-input-border-color);
1681
+ --bs-btn-active-color: var(--bs-body-color);
1682
+ --bs-btn-active-bg: var(--bs-tertiary-bg);
1683
+ --bs-btn-active-border-color: var(--d-input-border-color);
1684
+ --bs-btn-focus-box-shadow: #{$input-focus-box-shadow};
1685
+
1686
+ &:focus-visible {
1687
+ border-color: $input-focus-border-color;
1688
+ }
1689
+ }
1690
+
1691
+ // Disabled with its field: the disabled input's fill and border, not the
1692
+ // neutral outline-button look (`.btn:is(:disabled)` below), so the eye still
1693
+ // reads as part of the greyed-out control. `.input-group >` outranks that rule.
1694
+ .input-group > .btn.dx-password-reveal:is(:disabled, .disabled),
1695
+ fieldset:disabled .input-group > .btn.dx-password-reveal {
1696
+ --bs-btn-disabled-bg: #{$input-disabled-bg};
1697
+ --bs-btn-disabled-color: var(--bs-secondary-color);
1698
+ --bs-btn-disabled-border-color: var(--d-input-border-color);
1699
+ }
1700
+
1701
+ .dx-password-field {
1702
+ display: flex;
1703
+ flex-wrap: wrap;
1704
+ align-items: flex-start;
1705
+ gap: $dx-password-actions-gap;
1706
+
1707
+ > .dx-password-field__group {
1708
+ // The eye is an icon-only square, `--dx-input-height` wide.
1709
+ flex: 1 1 calc(var(--dx-password-input-min-width) + var(--dx-input-height));
1710
+ min-width: 0;
1711
+ }
1712
+ }
1713
+
1714
+ .dx-password-field__actions {
1715
+ display: flex;
1716
+ flex-wrap: wrap;
1717
+ gap: $dx-password-actions-gap;
1718
+ min-width: 0;
1719
+ max-width: 100%;
1720
+ }
1721
+
1647
1722
  // ----------------------------------------------------------------------------
1648
1723
  // DXCurrencyInput — keep the amount usable in a narrow container
1649
1724
  // ----------------------------------------------------------------------------