@eifi1/ui-kit 0.32.1 → 0.33.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 +16 -8
- package/dist/account/delete-account-setting.d.ts +10 -10
- package/dist/account/delete-account-setting.js +2 -1
- package/dist/account/delete-account-setting.js.map +1 -1
- package/dist/account/email-change-setting.d.ts +5 -0
- package/dist/account/email-change-setting.js +4 -3
- package/dist/account/email-change-setting.js.map +1 -1
- package/dist/account/sessions-setting.d.ts +4 -0
- package/dist/account/sessions-setting.js +3 -2
- package/dist/account/sessions-setting.js.map +1 -1
- package/dist/admin/admin-action-confirm.d.ts +10 -10
- package/dist/admin/admin-action-confirm.js.map +1 -1
- package/dist/admin/invitations-panel.d.ts +10 -10
- package/dist/admin/invitations-panel.js +4 -3
- package/dist/admin/invitations-panel.js.map +1 -1
- package/dist/admin/plan-change.d.ts +100 -0
- package/dist/admin/plan-change.js +208 -0
- package/dist/admin/plan-change.js.map +1 -0
- package/dist/admin/reviewer-scope-editor.d.ts +10 -10
- package/dist/admin/reviewer-scope-editor.js.map +1 -1
- package/dist/admin/role-select.d.ts +7 -7
- package/dist/admin/role-select.js.map +1 -1
- package/dist/admin/transfer-ownership-dialog.d.ts +10 -10
- package/dist/admin/user-roster.d.ts +7 -7
- package/dist/admin/user-roster.js +2 -2
- package/dist/admin/user-roster.js.map +1 -1
- package/dist/auth/auth-errors.d.ts +13 -2
- package/dist/auth/auth-errors.js +5 -1
- package/dist/auth/auth-errors.js.map +1 -1
- package/dist/auth/complete-name-dialog.d.ts +4 -1
- package/dist/auth/complete-name-dialog.js +2 -1
- package/dist/auth/complete-name-dialog.js.map +1 -1
- package/dist/auth/register-form.d.ts +10 -10
- package/dist/billing/billing-banner.d.ts +13 -11
- package/dist/billing/billing-banner.js.map +1 -1
- package/dist/billing/billing-labels.d.ts +10 -10
- package/dist/billing/billing-labels.js +10 -1
- package/dist/billing/billing-labels.js.map +1 -1
- package/dist/billing/billing-lock.d.ts +39 -12
- package/dist/billing/billing-lock.js +9 -3
- package/dist/billing/billing-lock.js.map +1 -1
- package/dist/billing/billing-overview.d.ts +154 -0
- package/dist/billing/billing-overview.js +2 -0
- package/dist/billing/billing-overview.js.map +1 -0
- package/dist/billing/billing-standing.d.ts +10 -10
- package/dist/billing/checkout-processing.d.ts +217 -0
- package/dist/billing/checkout-processing.js +198 -0
- package/dist/billing/checkout-processing.js.map +1 -0
- package/dist/billing/checkout-return.d.ts +51 -0
- package/dist/billing/checkout-return.js +43 -0
- package/dist/billing/checkout-return.js.map +1 -0
- package/dist/billing/pay-page.d.ts +210 -0
- package/dist/billing/pay-page.js +113 -0
- package/dist/billing/pay-page.js.map +1 -0
- package/dist/billing/plan-card.d.ts +10 -10
- package/dist/billing/plan-limit-notice.d.ts +10 -10
- package/dist/billing/plan-limit-toast.d.ts +143 -0
- package/dist/billing/plan-limit-toast.js +40 -0
- package/dist/billing/plan-limit-toast.js.map +1 -0
- package/dist/billing/subscription-actions.d.ts +38 -15
- package/dist/billing/subscription-actions.js +9 -2
- package/dist/billing/subscription-actions.js.map +1 -1
- package/dist/billing/subscription-status-chip.d.ts +9 -9
- package/dist/bin/eifi1-pay-page.mjs +166 -0
- package/dist/chart.d.ts +10 -10
- package/dist/components/account-chips.d.ts +6 -1
- package/dist/components/account-settings.d.ts +4 -1
- package/dist/components/account-settings.js +2 -1
- package/dist/components/account-settings.js.map +1 -1
- package/dist/components/amount-input.d.ts +10 -10
- package/dist/components/autocomplete.d.ts +2 -1
- package/dist/components/autocomplete.js +3 -1
- package/dist/components/autocomplete.js.map +1 -1
- package/dist/components/button-group.d.ts +10 -10
- package/dist/components/button-group.js +1 -1
- package/dist/components/button-group.js.map +1 -1
- package/dist/components/calculator.d.ts +10 -10
- package/dist/components/calculator.js +3 -3
- package/dist/components/calculator.js.map +1 -1
- package/dist/components/checkbox-group.d.ts +2 -1
- package/dist/components/checkbox-group.js.map +1 -1
- package/dist/components/checkbox.d.ts +2 -1
- package/dist/components/checkbox.js.map +1 -1
- package/dist/components/chip.d.ts +2 -1
- package/dist/components/chip.js +19 -17
- package/dist/components/chip.js.map +1 -1
- package/dist/components/choice-card.d.ts +3 -1
- package/dist/components/choice-card.js +1 -1
- package/dist/components/choice-card.js.map +1 -1
- package/dist/components/combobox.d.ts +4 -3
- package/dist/components/combobox.js.map +1 -1
- package/dist/components/confirm-dialog.d.ts +10 -10
- package/dist/components/confirm-dialog.js +6 -3
- package/dist/components/confirm-dialog.js.map +1 -1
- package/dist/components/copy-button.d.ts +11 -11
- package/dist/components/country-select.d.ts +2 -1
- package/dist/components/country-select.js.map +1 -1
- package/dist/components/danger-confirm.d.ts +10 -10
- package/dist/components/danger-confirm.js.map +1 -1
- package/dist/components/data-table-cells.d.ts +12 -1
- package/dist/components/data-table-filter-popover.d.ts +12 -1
- package/dist/components/data-table-filters.d.ts +12 -1
- package/dist/components/data-table-labels.d.ts +12 -1
- package/dist/components/data-table-pagination.d.ts +12 -1
- package/dist/components/data-table.d.ts +12 -1
- package/dist/components/data-table.js +3 -3
- package/dist/components/data-table.js.map +1 -1
- package/dist/components/date-picker.js +6 -4
- package/dist/components/date-picker.js.map +1 -1
- package/dist/components/entity-combobox.d.ts +3 -2
- package/dist/components/entity-combobox.js.map +1 -1
- package/dist/components/facing-pair.d.ts +10 -10
- package/dist/components/field-parts.d.ts +32 -4
- package/dist/components/field-parts.js +54 -19
- package/dist/components/field-parts.js.map +1 -1
- package/dist/components/file-button.d.ts +10 -10
- package/dist/components/file-button.js +3 -2
- package/dist/components/file-button.js.map +1 -1
- package/dist/components/file-dropzone.d.ts +11 -11
- package/dist/components/file-dropzone.js.map +1 -1
- package/dist/components/floating-panel.js +5 -5
- package/dist/components/floating-panel.js.map +1 -1
- package/dist/components/form-actions.d.ts +9 -9
- package/dist/components/form-actions.js +3 -3
- package/dist/components/form-actions.js.map +1 -1
- package/dist/components/iban-input.d.ts +10 -10
- package/dist/components/inline-edit-field.d.ts +2 -1
- package/dist/components/inline-edit-field.js +6 -6
- package/dist/components/inline-edit-field.js.map +1 -1
- package/dist/components/language-select.d.ts +10 -10
- package/dist/components/legal-page.d.ts +10 -10
- package/dist/components/legal.d.ts +10 -10
- package/dist/components/list.d.ts +2 -1
- package/dist/components/list.js +4 -5
- package/dist/components/list.js.map +1 -1
- package/dist/components/money-field.d.ts +10 -10
- package/dist/components/month-picker.js +54 -44
- package/dist/components/month-picker.js.map +1 -1
- package/dist/components/multi-entity-combobox.d.ts +3 -2
- package/dist/components/multi-entity-combobox.js.map +1 -1
- package/dist/components/number-field.d.ts +10 -10
- package/dist/components/number-input.d.ts +10 -10
- package/dist/components/numpad-sheet.d.ts +10 -10
- package/dist/components/numpad-sheet.js +2 -2
- package/dist/components/numpad-sheet.js.map +1 -1
- package/dist/components/page-header.js +6 -1
- package/dist/components/page-header.js.map +1 -1
- package/dist/components/phone-input.d.ts +10 -10
- package/dist/components/popover.d.ts +1 -1
- package/dist/components/popover.js +2 -0
- package/dist/components/popover.js.map +1 -1
- package/dist/components/row-actions.d.ts +5 -5
- package/dist/components/row-actions.js +130 -38
- package/dist/components/row-actions.js.map +1 -1
- package/dist/components/series-chart.d.ts +10 -10
- package/dist/components/settings-fields.d.ts +10 -10
- package/dist/components/share-card.d.ts +7 -7
- package/dist/components/share-card.js +26 -10
- package/dist/components/share-card.js.map +1 -1
- package/dist/components/status-dot.d.ts +1 -0
- package/dist/components/status-dot.js +2 -2
- package/dist/components/status-dot.js.map +1 -1
- package/dist/components/swatch-picker.d.ts +2 -1
- package/dist/components/swatch-picker.js.map +1 -1
- package/dist/components/swipeable-row.d.ts +88 -17
- package/dist/components/swipeable-row.js +46 -9
- package/dist/components/swipeable-row.js.map +1 -1
- package/dist/components/switch.d.ts +2 -1
- package/dist/components/switch.js.map +1 -1
- package/dist/components/table.d.ts +2 -1
- package/dist/components/table.js +6 -0
- package/dist/components/table.js.map +1 -1
- package/dist/components/text-link.d.ts +9 -9
- package/dist/components/time-input.d.ts +10 -10
- package/dist/components/toggle-group.d.ts +2 -1
- package/dist/components/toggle-group.js +1 -1
- package/dist/components/toggle-group.js.map +1 -1
- package/dist/components/translation-review-editor.d.ts +4 -0
- package/dist/components/translation-review-editor.js +4 -3
- package/dist/components/translation-review-editor.js.map +1 -1
- package/dist/components/translation-review-parts.d.ts +1 -0
- package/dist/components/translation-review.d.ts +1 -0
- package/dist/components/translation-review.js +15 -18
- package/dist/components/translation-review.js.map +1 -1
- package/dist/components/ui.d.ts +9 -9
- package/dist/components/ui.js +48 -28
- package/dist/components/ui.js.map +1 -1
- package/dist/components/use-table-state.d.ts +12 -1
- package/dist/components/user-avatar.d.ts +1 -0
- package/dist/components/write-lock.d.ts +101 -13
- package/dist/components/write-lock.js +37 -13
- package/dist/components/write-lock.js.map +1 -1
- package/dist/{data-table-labels-kpAAVi6g.d.ts → data-table-labels-BJ5JE_X2.d.ts} +17 -0
- package/dist/data-table.d.ts +12 -1
- package/dist/{delete-account-setting-FLyJf-kZ.d.ts → delete-account-setting-DiPX4Vue.d.ts} +365 -47
- package/dist/feedback/feedback-attachment.d.ts +10 -10
- package/dist/feedback/feedback-attachment.js +7 -7
- package/dist/feedback/feedback-attachment.js.map +1 -1
- package/dist/feedback/feedback-context.d.ts +10 -10
- package/dist/feedback/feedback-crash.d.ts +10 -10
- package/dist/feedback/feedback-dialog.d.ts +10 -10
- package/dist/feedback/feedback-inbox.d.ts +9 -9
- package/dist/feedback/feedback-inbox.js +7 -3
- package/dist/feedback/feedback-inbox.js.map +1 -1
- package/dist/feedback/feedback-labels.d.ts +10 -10
- package/dist/feedback/feedback-menu.d.ts +3 -3
- package/dist/feedback/feedback-record.d.ts +10 -10
- package/dist/feedback/feedback-row-detail.d.ts +10 -10
- package/dist/feedback/feedback-row-detail.js.map +1 -1
- package/dist/feedback/feedback-status-undo.d.ts +10 -10
- package/dist/feedback/feedback-submit.d.ts +10 -10
- package/dist/feedback/feedback-swipe.d.ts +10 -10
- package/dist/feedback/feedback-swipe.js +3 -6
- package/dist/feedback/feedback-swipe.js.map +1 -1
- package/dist/feedback/feedback-table.d.ts +10 -10
- package/dist/feedback/feedback-table.js.map +1 -1
- package/dist/feedback/feedback-thread.d.ts +10 -10
- package/dist/feedback.d.ts +10 -10
- package/dist/hooks/use-file-drop.d.ts +10 -10
- package/dist/i18n/defaults.d.ts +10 -10
- package/dist/i18n/defaults.js +2 -0
- package/dist/i18n/defaults.js.map +1 -1
- package/dist/i18n/german.d.ts +10 -10
- package/dist/i18n/german.js +34 -1
- package/dist/i18n/german.js.map +1 -1
- package/dist/i18n/kit-labels.d.ts +4 -4
- package/dist/i18n/kit-labels.js.map +1 -1
- package/dist/i18n/languages.d.ts +10 -10
- package/dist/i18n/locales/de-CH.d.ts +10 -10
- package/dist/i18n/locales/en.d.ts +10 -10
- package/dist/i18n/locales/es.d.ts +10 -10
- package/dist/i18n/locales/es.js +34 -1
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +10 -10
- package/dist/i18n/locales/fr.js +35 -1
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hu.d.ts +10 -10
- package/dist/i18n/locales/hu.js +36 -1
- package/dist/i18n/locales/hu.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +10 -10
- package/dist/i18n/locales/it.js +34 -1
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +10 -10
- package/dist/i18n/locales/zh.js +34 -1
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/review.d.ts +10 -10
- package/dist/i18n/review.js +8 -1
- package/dist/i18n/review.js.map +1 -1
- package/dist/index.d.ts +10 -5
- package/dist/index.js +40 -2
- package/dist/index.js.map +1 -1
- package/dist/landing/landing-actions.d.ts +10 -10
- package/dist/landing/landing-sections.d.ts +10 -10
- package/dist/landing/public-header.d.ts +10 -10
- package/dist/landing/routing.d.ts +10 -10
- package/dist/pay/.well-known/apple-developer-merchantid-domain-association +1 -0
- package/dist/pay/index.html +30 -0
- package/dist/pay/pay.css +126 -0
- package/dist/pay/pay.js +198 -0
- package/dist/rhf/fields.d.ts +10 -10
- package/dist/rhf/form.d.ts +10 -10
- package/dist/rhf.d.ts +10 -10
- package/dist/settings/settings-section.d.ts +10 -10
- package/dist/shell/app-shell.d.ts +9 -9
- package/dist/shell/app-shell.js +2 -1
- package/dist/shell/app-shell.js.map +1 -1
- package/dist/shell/top-bar-brand.d.ts +10 -10
- package/dist/shell/topbar-action-menu.d.ts +1 -0
- package/dist/shell.d.ts +10 -10
- package/dist/testing/css-variables.d.ts +74 -0
- package/dist/testing/css-variables.generated.d.ts +7 -0
- package/dist/testing/css-variables.generated.js +8 -0
- package/dist/testing/css-variables.generated.js.map +1 -0
- package/dist/testing/css-variables.js +93 -0
- package/dist/testing/css-variables.js.map +1 -0
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +12 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/theme/contrast-tokens.d.ts +44 -1
- package/dist/theme/contrast-tokens.js +21 -0
- package/dist/theme/contrast-tokens.js.map +1 -1
- package/dist/theme/contrast.d.ts +2 -2
- package/dist/theme/palette-derive.js +60 -11
- package/dist/theme/palette-derive.js.map +1 -1
- package/dist/theme/palette-presets.js +45 -43
- package/dist/theme/palette-presets.js.map +1 -1
- package/dist/wizard/stepper-nav.d.ts +11 -11
- package/dist/wizard/stepper-nav.js.map +1 -1
- package/dist/wizard.d.ts +10 -10
- package/package.json +10 -2
- package/src/account/delete-account-setting.tsx +6 -1
- package/src/account/email-change-setting.tsx +9 -3
- package/src/account/sessions-setting.tsx +7 -2
- package/src/admin/admin-action-confirm.tsx +2 -1
- package/src/admin/invitations-panel.tsx +9 -3
- package/src/admin/plan-change.tsx +459 -0
- package/src/admin/reviewer-scope-editor.tsx +2 -1
- package/src/admin/role-select.tsx +2 -1
- package/src/admin/user-roster.tsx +5 -3
- package/src/auth/auth-errors.ts +25 -2
- package/src/auth/complete-name-dialog.tsx +6 -2
- package/src/billing/billing-banner.tsx +3 -1
- package/src/billing/billing-labels.ts +45 -0
- package/src/billing/billing-lock.ts +36 -3
- package/src/billing/billing-overview.ts +58 -0
- package/src/billing/checkout-processing.ts +391 -0
- package/src/billing/checkout-return.ts +90 -0
- package/src/billing/pay-page.ts +242 -0
- package/src/billing/plan-limit-toast.tsx +91 -0
- package/src/billing/subscription-actions.tsx +41 -8
- package/src/components/account-settings.tsx +6 -2
- package/src/components/autocomplete.tsx +5 -2
- package/src/components/button-group.tsx +4 -1
- package/src/components/calculator.tsx +10 -6
- package/src/components/checkbox-group.tsx +2 -2
- package/src/components/checkbox.tsx +2 -1
- package/src/components/chip.tsx +37 -32
- package/src/components/choice-card.tsx +4 -2
- package/src/components/combobox.tsx +4 -4
- package/src/components/confirm-dialog.tsx +13 -6
- package/src/components/country-select.tsx +2 -2
- package/src/components/danger-confirm.tsx +2 -2
- package/src/components/data-table.tsx +20 -9
- package/src/components/date-picker.tsx +10 -7
- package/src/components/entity-combobox.tsx +3 -3
- package/src/components/field-parts.tsx +61 -14
- package/src/components/file-button.tsx +5 -4
- package/src/components/file-dropzone.tsx +2 -2
- package/src/components/floating-panel.tsx +7 -5
- package/src/components/form-actions.tsx +12 -5
- package/src/components/inline-edit-field.tsx +13 -13
- package/src/components/list.tsx +10 -9
- package/src/components/month-picker.tsx +8 -2
- package/src/components/multi-entity-combobox.tsx +3 -3
- package/src/components/numpad-sheet.tsx +8 -4
- package/src/components/page-header.tsx +15 -1
- package/src/components/popover.tsx +4 -0
- package/src/components/row-actions.tsx +201 -50
- package/src/components/share-card.tsx +67 -13
- package/src/components/status-dot.tsx +7 -7
- package/src/components/swatch-picker.tsx +2 -2
- package/src/components/swipeable-row.tsx +138 -27
- package/src/components/switch.tsx +2 -1
- package/src/components/table.tsx +8 -1
- package/src/components/toggle-group.tsx +5 -3
- package/src/components/translation-review-editor.tsx +8 -3
- package/src/components/translation-review.tsx +18 -22
- package/src/components/ui.tsx +98 -44
- package/src/components/write-lock.tsx +150 -24
- package/src/feedback/feedback-attachment.tsx +13 -9
- package/src/feedback/feedback-inbox.tsx +10 -6
- package/src/feedback/feedback-row-detail.tsx +3 -2
- package/src/feedback/feedback-swipe.tsx +6 -11
- package/src/feedback/feedback-table.tsx +2 -1
- package/src/i18n/defaults.ts +2 -0
- package/src/i18n/german.ts +38 -0
- package/src/i18n/kit-labels.tsx +4 -0
- package/src/i18n/locales/es.ts +34 -0
- package/src/i18n/locales/fr.ts +39 -0
- package/src/i18n/locales/hu.ts +37 -0
- package/src/i18n/locales/it.ts +35 -0
- package/src/i18n/locales/zh.ts +33 -0
- package/src/i18n/review.ts +7 -0
- package/src/index.ts +48 -4
- package/src/shell/app-shell.tsx +11 -6
- package/src/testing/css-variables.generated.ts +112 -0
- package/src/testing/css-variables.ts +191 -0
- package/src/testing/index.ts +13 -0
- package/src/theme/contrast-tokens.ts +53 -2
- package/src/theme/palette-derive.ts +87 -10
- package/src/theme/palette-presets.ts +45 -43
- package/src/wizard/stepper-nav.tsx +2 -1
- package/tokens.css +306 -46
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import 'react';
|
|
2
2
|
import './data-table-sort.js';
|
|
3
|
-
export { I as DEFAULT_PERSIST_PREFIX, T as TableUrlState, k as TableUrlStateProps, l as TableUrlSync, U as UseTableUrlStateOptions, m as UseTableUrlStateReturn, w as readTableUrlState, J as useTableState, E as useTableUrlState } from '../data-table-labels-
|
|
3
|
+
export { I as DEFAULT_PERSIST_PREFIX, T as TableUrlState, k as TableUrlStateProps, l as TableUrlSync, U as UseTableUrlStateOptions, m as UseTableUrlStateReturn, w as readTableUrlState, J as useTableState, E as useTableUrlState } from '../data-table-labels-BJ5JE_X2.js';
|
|
4
4
|
import './swipeable-row.js';
|
|
5
|
+
import './status-dot.js';
|
|
6
|
+
import './progress-bar.js';
|
|
7
|
+
import './signed-amount.js';
|
|
8
|
+
import './stat-tile.js';
|
|
9
|
+
import './chip.js';
|
|
10
|
+
import 'lucide-react';
|
|
11
|
+
import './field-parts.js';
|
|
12
|
+
import './tooltip.js';
|
|
13
|
+
import '../hooks/use-anchored-rect.js';
|
|
14
|
+
import '../lib/clipping.js';
|
|
15
|
+
import './write-lock.js';
|
|
@@ -11,6 +11,7 @@ import './field-parts.js';
|
|
|
11
11
|
import './tooltip.js';
|
|
12
12
|
import '../hooks/use-anchored-rect.js';
|
|
13
13
|
import '../lib/clipping.js';
|
|
14
|
+
import './write-lock.js';
|
|
14
15
|
|
|
15
16
|
/** Initials from a display name (first + last) or, failing that, an email —
|
|
16
17
|
* e.g. "Marcel Eifert" → "ME", "marcel@x.com" → "MA". App-agnostic.
|
|
@@ -7,12 +7,62 @@ interface WriteLockLabels {
|
|
|
7
7
|
reason: string;
|
|
8
8
|
}
|
|
9
9
|
declare const DEFAULT_WRITE_LOCK_LABELS: WriteLockLabels;
|
|
10
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* What kind of lock a source is (docs/billing-harmonization.md §12.36, ui-kit 0.33).
|
|
12
|
+
* `"demo"` (the read-only demo, `demo.writeLocked`) and `"billing"` (a lapsed plan,
|
|
13
|
+
* `billing.lockReason`) are the kit's; an app names its own — Kurvenschmiede's
|
|
14
|
+
* `"access"` (a curve shared to view) and `"customer"` (an account that owns nothing).
|
|
15
|
+
* A control exempts itself from a kind with {@link CommitScope}; a source without a
|
|
16
|
+
* kind is never exempted.
|
|
17
|
+
*/
|
|
18
|
+
type WriteLockKind = "demo" | "billing" | (string & {});
|
|
19
|
+
/** One locked source, as the provider holds it: its kind and its one sentence. */
|
|
20
|
+
interface WriteLockHold {
|
|
21
|
+
kind: WriteLockKind | undefined;
|
|
22
|
+
reason: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A control's opt-in to the lock — the type of every `commit` prop in the kit.
|
|
26
|
+
*
|
|
27
|
+
* - `true`: every lock refuses the control (a save, an add, an invite).
|
|
28
|
+
* - `{ except: [kinds] }`: every lock but those kinds. A billing lock leaves the
|
|
29
|
+
* reader able to remove access, revoke sessions, delete the account and change their
|
|
30
|
+
* own settings (§3.3, §12.13), so the kit's parts for those take
|
|
31
|
+
* {@link COMMIT_EXCEPT_BILLING} built in, and an app's own controls of that sort do
|
|
32
|
+
* too.
|
|
33
|
+
* - `false` or left out: no lock reaches it.
|
|
34
|
+
*
|
|
35
|
+
* Under a demo lock and a billing lock together, a control exempt from billing is
|
|
36
|
+
* still refused, with the demo's reason.
|
|
37
|
+
*/
|
|
38
|
+
type CommitScope = boolean | {
|
|
39
|
+
readonly except: readonly WriteLockKind[];
|
|
40
|
+
};
|
|
41
|
+
/** Every lock but billing's: the scope of an action a lapsed plan still allows — removing
|
|
42
|
+
* access, the account's own settings, an operator's admin route (§12.13). One constant,
|
|
43
|
+
* so the call sites read alike. */
|
|
44
|
+
declare const COMMIT_EXCEPT_BILLING: {
|
|
45
|
+
readonly except: readonly ["billing"];
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* What {@link useWriteLock} returns: whether commits are locked here as a control with
|
|
49
|
+
* the scope asked for sees it, and why.
|
|
50
|
+
*/
|
|
11
51
|
interface WriteLock {
|
|
12
52
|
locked: boolean;
|
|
13
|
-
/** The one sentence a locked commit shows in its tooltip
|
|
14
|
-
* `locked`; `undefined` when not. */
|
|
53
|
+
/** The one sentence a locked commit shows in its tooltip: the first hold in scope's.
|
|
54
|
+
* Always set while `locked`; `undefined` when not. */
|
|
15
55
|
reason: ReactNode | undefined;
|
|
56
|
+
/** The first hold in scope's kind; `undefined` while unlocked, or for a source that
|
|
57
|
+
* names none. */
|
|
58
|
+
kind: WriteLockKind | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* EVERY locked source the provider holds, in the order the server refuses them
|
|
61
|
+
* (§12.3: the demo's 403 before billing's 402) — unfiltered by the scope, for code
|
|
62
|
+
* that must know what else locks (a toast that names the plan, a swipe plan). Empty
|
|
63
|
+
* while the provider is unlocked.
|
|
64
|
+
*/
|
|
65
|
+
holds: readonly WriteLockHold[];
|
|
16
66
|
}
|
|
17
67
|
interface WriteLockProviderProps {
|
|
18
68
|
/** Commits below are locked. `false` unlocks a subtree under an outer lock. */
|
|
@@ -23,6 +73,17 @@ interface WriteLockProviderProps {
|
|
|
23
73
|
* already translated. Left out: `labels.reason`.
|
|
24
74
|
*/
|
|
25
75
|
reason?: ReactNode;
|
|
76
|
+
/** What kind of lock this is — `"demo"`, `"billing"` or the app's own (see
|
|
77
|
+
* {@link WriteLockKind}), for a provider of one source. Left out, no control can be
|
|
78
|
+
* exempt from it. */
|
|
79
|
+
kind?: WriteLockKind;
|
|
80
|
+
/**
|
|
81
|
+
* Every locked source, in refusal order — what `combineWriteLocks` answers, so
|
|
82
|
+
* `<WriteLockProvider {...combineWriteLocks([...])}>` carries them. Given while
|
|
83
|
+
* `locked`, it wins over `kind` and `reason`; a hold without a reason takes
|
|
84
|
+
* `labels.reason`.
|
|
85
|
+
*/
|
|
86
|
+
holds?: readonly WriteLockHold[];
|
|
26
87
|
labels?: Partial<WriteLockLabels>;
|
|
27
88
|
children?: ReactNode;
|
|
28
89
|
}
|
|
@@ -50,19 +111,46 @@ interface WriteLockProviderProps {
|
|
|
50
111
|
* {@link useWriteLock} and disables itself. The lock is a courtesy, not a guard: the
|
|
51
112
|
* server still refuses the write.
|
|
52
113
|
*
|
|
114
|
+
* **A lock says its source** (0.33, docs/billing-harmonization.md §12.36). A lapsed
|
|
115
|
+
* plan locks creating and changing, but not removing access or the account's own
|
|
116
|
+
* settings (§3.3, §12.13), and the kit's parts for those hard-coded `commit` — so
|
|
117
|
+
* kastlan's app-wide lock locked a member's own sign-out everywhere. Each source now
|
|
118
|
+
* has a kind, the provider holds every locked one in order (`holds`, from
|
|
119
|
+
* `combineWriteLocks`), and a control's `commit` may name the kinds it is exempt from
|
|
120
|
+
* ({@link CommitScope}). The kit's parts follow §3.3 and §12.13 by themselves.
|
|
121
|
+
*
|
|
53
122
|
* Nested providers: the nearest wins, so an inner `locked={false}` reopens a section
|
|
54
|
-
* the caller may write (a viewer's own notes on a shared curve)
|
|
55
|
-
* with its own reason (Kurvenschmiede's owner lock beside the
|
|
56
|
-
* the outer one's sentence.
|
|
123
|
+
* the caller may write (a viewer's own notes on a shared curve) — every source at
|
|
124
|
+
* once — and an inner lock with its own reason (Kurvenschmiede's owner lock beside the
|
|
125
|
+
* viewer lock) overrides the outer one's sentence and its holds.
|
|
126
|
+
*/
|
|
127
|
+
declare function WriteLockProvider({ locked, reason, kind, holds, labels, children }: WriteLockProviderProps): react.JSX.Element;
|
|
128
|
+
/**
|
|
129
|
+
* The lock as a control with `scope` sees it — {@link useWriteLock}'s answer, pure, for
|
|
130
|
+
* a scope known only at call time: `useConfirm` reads the CALLER's lock when it is
|
|
131
|
+
* called, and applies each `confirm({ commit })`'s own scope to it when it runs.
|
|
132
|
+
*
|
|
133
|
+
* `undefined` and `false` see no lock (a control without `commit`); `true` sees the
|
|
134
|
+
* lock as it is; `{ except }` sees the first hold of another kind, with its reason
|
|
135
|
+
* and kind. `holds` is passed on unfiltered.
|
|
136
|
+
*/
|
|
137
|
+
declare function writeLockFor(lock: WriteLock, scope: CommitScope | undefined): WriteLock;
|
|
138
|
+
/**
|
|
139
|
+
* The nearest {@link WriteLockProvider}'s lock, as a control with `scope` sees it —
|
|
140
|
+
* unlocked with no provider. Left out, the scope is `true`: every lock.
|
|
141
|
+
*
|
|
142
|
+
* For code that must KNOW rather than a control that opts in: a toast that says why,
|
|
143
|
+
* a swipe plan that leaves an action out, a hand-rolled toggle that disables itself.
|
|
144
|
+
* `useWriteLock(COMMIT_EXCEPT_BILLING)` answers "would a lapsed plan's lock refuse me?"
|
|
145
|
+
* as a removal sees it — what keksdose's `useWriteLockKind() !== "billing"` asked.
|
|
57
146
|
*/
|
|
58
|
-
declare function
|
|
59
|
-
/** The nearest {@link WriteLockProvider}'s lock; unlocked with no provider. */
|
|
60
|
-
declare function useWriteLock(): WriteLock;
|
|
147
|
+
declare function useWriteLock(scope?: CommitScope): WriteLock;
|
|
61
148
|
/**
|
|
62
149
|
* The `disabledReason` a control with `commit` should use: the lock's reason while
|
|
63
|
-
*
|
|
64
|
-
* hover is asking — else the control's own. Internal to the kit's
|
|
150
|
+
* the lock refuses this scope — it wins over the control's own, since it is the answer
|
|
151
|
+
* to the question the hover is asking — else the control's own. Internal to the kit's
|
|
152
|
+
* commit controls.
|
|
65
153
|
*/
|
|
66
|
-
declare function useCommitReason(commit:
|
|
154
|
+
declare function useCommitReason(commit: CommitScope | undefined, own: ReactNode): ReactNode;
|
|
67
155
|
|
|
68
|
-
export { DEFAULT_WRITE_LOCK_LABELS, type WriteLock, type WriteLockLabels, WriteLockProvider, type WriteLockProviderProps, useCommitReason, useWriteLock };
|
|
156
|
+
export { COMMIT_EXCEPT_BILLING, type CommitScope, DEFAULT_WRITE_LOCK_LABELS, type WriteLock, type WriteLockHold, type WriteLockKind, type WriteLockLabels, WriteLockProvider, type WriteLockProviderProps, useCommitReason, useWriteLock, writeLockFor };
|
|
@@ -5,29 +5,53 @@ import { useKitLabels } from "../i18n/kit-labels.js";
|
|
|
5
5
|
const DEFAULT_WRITE_LOCK_LABELS = {
|
|
6
6
|
reason: "You can view this but not change it."
|
|
7
7
|
};
|
|
8
|
-
const
|
|
8
|
+
const COMMIT_EXCEPT_BILLING = { except: ["billing"] };
|
|
9
|
+
const NO_HOLDS = [];
|
|
10
|
+
const UNLOCKED = { locked: false, reason: void 0, kind: void 0, holds: NO_HOLDS };
|
|
9
11
|
const WriteLockContext = createContext(UNLOCKED);
|
|
10
|
-
function
|
|
12
|
+
function given(reason) {
|
|
13
|
+
return reason !== void 0 && reason !== null && reason !== false && reason !== "";
|
|
14
|
+
}
|
|
15
|
+
function WriteLockProvider({ locked, reason, kind, holds, labels, children }) {
|
|
11
16
|
const fallback = useKitLabels("writeLock", DEFAULT_WRITE_LOCK_LABELS, labels).reason;
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
)
|
|
17
|
+
const several = locked && holds !== void 0 && holds.length > 0 ? holds : void 0;
|
|
18
|
+
const firstKind = several ? several[0].kind : kind;
|
|
19
|
+
const firstGiven = several ? several[0].reason : reason;
|
|
20
|
+
const firstReason = given(firstGiven) ? firstGiven : fallback;
|
|
21
|
+
const many = several && several.length > 1 ? several : void 0;
|
|
22
|
+
const value = useMemo(() => {
|
|
23
|
+
if (!locked) return UNLOCKED;
|
|
24
|
+
const all = many ? many.map((hold) => ({ kind: hold.kind, reason: given(hold.reason) ? hold.reason : fallback })) : [{ kind: firstKind, reason: firstReason }];
|
|
25
|
+
return { locked: true, reason: firstReason, kind: firstKind, holds: all };
|
|
26
|
+
}, [locked, many, firstKind, firstReason, fallback]);
|
|
18
27
|
return /* @__PURE__ */ jsx(WriteLockContext.Provider, { value, children });
|
|
19
28
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
29
|
+
function inScope(hold, scope) {
|
|
30
|
+
if (scope === true) return true;
|
|
31
|
+
if (scope === false) return false;
|
|
32
|
+
return hold.kind === void 0 || !scope.except.includes(hold.kind);
|
|
33
|
+
}
|
|
34
|
+
function writeLockFor(lock, scope) {
|
|
35
|
+
if (!lock.locked || scope === true) return lock;
|
|
36
|
+
const holds = lock.holds.length > 0 ? lock.holds : [{ kind: lock.kind, reason: lock.reason }];
|
|
37
|
+
const first = scope === void 0 ? void 0 : holds.find((hold) => inScope(hold, scope));
|
|
38
|
+
if (!first) return { ...UNLOCKED, holds: lock.holds };
|
|
39
|
+
if (first === holds[0]) return lock;
|
|
40
|
+
return { locked: true, reason: first.reason, kind: first.kind, holds: lock.holds };
|
|
41
|
+
}
|
|
42
|
+
function useWriteLock(scope = true) {
|
|
43
|
+
return writeLockFor(useContext(WriteLockContext), scope);
|
|
22
44
|
}
|
|
23
45
|
function useCommitReason(commit, own) {
|
|
24
|
-
const lock =
|
|
25
|
-
return
|
|
46
|
+
const lock = writeLockFor(useContext(WriteLockContext), commit);
|
|
47
|
+
return lock.locked ? lock.reason : own;
|
|
26
48
|
}
|
|
27
49
|
export {
|
|
50
|
+
COMMIT_EXCEPT_BILLING,
|
|
28
51
|
DEFAULT_WRITE_LOCK_LABELS,
|
|
29
52
|
WriteLockProvider,
|
|
30
53
|
useCommitReason,
|
|
31
|
-
useWriteLock
|
|
54
|
+
useWriteLock,
|
|
55
|
+
writeLockFor
|
|
32
56
|
};
|
|
33
57
|
//# sourceMappingURL=write-lock.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/write-lock.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useKitLabels } from \"../i18n/kit-labels\";\n\n/** The words {@link WriteLockProvider} renders on its own behalf. */\nexport interface WriteLockLabels {\n /** The tooltip of a locked commit when the provider gives no `reason`. */\n reason: string;\n}\n\nexport const DEFAULT_WRITE_LOCK_LABELS: WriteLockLabels = {\n reason: \"You can view this but not change it.\",\n};\n\n/** What {@link useWriteLock} returns: whether commits are locked here, and why. */\nexport interface WriteLock {\n locked: boolean;\n /** The one sentence a locked commit shows in its tooltip. Always set while\n * `locked`; `undefined` when not. */\n reason: ReactNode | undefined;\n}\n\nconst UNLOCKED: WriteLock = { locked: false, reason: undefined };\n\nconst WriteLockContext = createContext<WriteLock>(UNLOCKED);\n\nexport interface WriteLockProviderProps {\n /** Commits below are locked. `false` unlocks a subtree under an outer lock. */\n locked: boolean;\n /**\n * The one sentence that says why — \"Shared with you to read\", \"Read-only demo —\n * saving is disabled\", \"A customer account cannot create curves\". The app's policy,\n * already translated. Left out: `labels.reason`.\n */\n reason?: ReactNode;\n labels?: Partial<WriteLockLabels>;\n children?: ReactNode;\n}\n\n/**\n * The read-only lock — **everything renders; only the commit is locked.**\n *\n * keksdose (features/budgets/write-lock.tsx, the read-only demo budget) and\n * Kurvenschmiede (features/sharing/write-lock.tsx, a curve shared to view, a customer\n * account that owns nothing) each built the same `SaveGuard`: the page, its tabs,\n * forms and dialogs render exactly as for an owner, because a viewer looking at half\n * a page is not looking at what they were sent; what changes is that the control\n * that SAVES is off and says why on hover or focus. Both wrapped each Save in a\n * Tooltip and forced a native `disabled` on it — out of the tab order, so the reason\n * never reached a keyboard — and both had to remember it at thirty call sites.\n *\n * Here the page mounts one provider and each commit control opts in with `commit`\n * ({@link Button}, {@link IconButton}, {@link FormActions}): under a lock it takes the\n * kit's `disabledReason` path with this reason — `aria-disabled` and focusable,\n * every activation swallowed, the reason in the kit Tooltip and its description.\n *\n * Who is locked is the app's: the provider takes a boolean, never a role. Fields stay\n * editable — nothing in them reaches the server until the commit is pressed, and a\n * form you cannot fill in is not a demo of the form (keksdose accounts-page). A\n * control that IS its own commit (a toggle that saves on change) reads\n * {@link useWriteLock} and disables itself. The lock is a courtesy, not a guard: the\n * server still refuses the write.\n *\n * Nested providers: the nearest wins, so an inner `locked={false}` reopens a section\n * the caller may write (a viewer's own notes on a shared curve), and an inner lock\n * with its own reason (Kurvenschmiede's owner lock beside the viewer lock) overrides\n * the outer one's sentence.\n */\nexport function WriteLockProvider({ locked, reason, labels, children }: WriteLockProviderProps) {\n // The `writeLock` namespace: prop > `<UiKitProvider labels>` > English.\n const fallback = useKitLabels(\"writeLock\", DEFAULT_WRITE_LOCK_LABELS, labels).reason;\n // `null`/`\"\"`/`false` count as \"no reason given\": a lock whose tooltip is empty\n // would be a disabled button that cannot say why, the thing this replaces.\n const given = reason !== undefined && reason !== null && reason !== false && reason !== \"\";\n const resolved = locked ? (given ? reason : fallback) : undefined;\n const value = useMemo<WriteLock>(\n () => (locked ? { locked: true, reason: resolved } : UNLOCKED),\n [locked, resolved],\n );\n return <WriteLockContext.Provider value={value}>{children}</WriteLockContext.Provider>;\n}\n\n/** The nearest {@link WriteLockProvider}'s lock; unlocked with no provider. */\nexport function useWriteLock(): WriteLock {\n return useContext(WriteLockContext);\n}\n\n/**\n * The `disabledReason` a control with `commit` should use: the lock's reason while\n * locked — it wins over the control's own, since it is the answer to the question the\n * hover is asking — else the control's own. Internal to the kit's commit controls.\n */\nexport function useCommitReason(commit: boolean | undefined, own: ReactNode): ReactNode {\n const lock = useWriteLock();\n return commit && lock.locked ? lock.reason : own;\n}\n"],"mappings":";AA+ES;AA/ET,SAAS,eAAe,YAAY,eAAe;AAEnD,SAAS,oBAAoB;AAQtB,MAAM,4BAA6C;AAAA,EACxD,QAAQ;AACV;AAUA,MAAM,WAAsB,EAAE,QAAQ,OAAO,QAAQ,OAAU;AAE/D,MAAM,mBAAmB,cAAyB,QAAQ;AA4CnD,SAAS,kBAAkB,EAAE,QAAQ,QAAQ,QAAQ,SAAS,GAA2B;AAE9F,QAAM,WAAW,aAAa,aAAa,2BAA2B,MAAM,EAAE;AAG9E,QAAM,QAAQ,WAAW,UAAa,WAAW,QAAQ,WAAW,SAAS,WAAW;AACxF,QAAM,WAAW,SAAU,QAAQ,SAAS,WAAY;AACxD,QAAM,QAAQ;AAAA,IACZ,MAAO,SAAS,EAAE,QAAQ,MAAM,QAAQ,SAAS,IAAI;AAAA,IACrD,CAAC,QAAQ,QAAQ;AAAA,EACnB;AACA,SAAO,oBAAC,iBAAiB,UAAjB,EAA0B,OAAe,UAAS;AAC5D;AAGO,SAAS,eAA0B;AACxC,SAAO,WAAW,gBAAgB;AACpC;AAOO,SAAS,gBAAgB,QAA6B,KAA2B;AACtF,QAAM,OAAO,aAAa;AAC1B,SAAO,UAAU,KAAK,SAAS,KAAK,SAAS;AAC/C;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/components/write-lock.tsx"],"sourcesContent":["import { createContext, useContext, useMemo } from \"react\";\nimport type { ReactNode } from \"react\";\nimport { useKitLabels } from \"../i18n/kit-labels\";\n\n/** The words {@link WriteLockProvider} renders on its own behalf. */\nexport interface WriteLockLabels {\n /** The tooltip of a locked commit when the provider gives no `reason`. */\n reason: string;\n}\n\nexport const DEFAULT_WRITE_LOCK_LABELS: WriteLockLabels = {\n reason: \"You can view this but not change it.\",\n};\n\n/**\n * What kind of lock a source is (docs/billing-harmonization.md §12.36, ui-kit 0.33).\n * `\"demo\"` (the read-only demo, `demo.writeLocked`) and `\"billing\"` (a lapsed plan,\n * `billing.lockReason`) are the kit's; an app names its own — Kurvenschmiede's\n * `\"access\"` (a curve shared to view) and `\"customer\"` (an account that owns nothing).\n * A control exempts itself from a kind with {@link CommitScope}; a source without a\n * kind is never exempted.\n */\nexport type WriteLockKind = \"demo\" | \"billing\" | (string & {});\n\n/** One locked source, as the provider holds it: its kind and its one sentence. */\nexport interface WriteLockHold {\n kind: WriteLockKind | undefined;\n reason: ReactNode;\n}\n\n/**\n * A control's opt-in to the lock — the type of every `commit` prop in the kit.\n *\n * - `true`: every lock refuses the control (a save, an add, an invite).\n * - `{ except: [kinds] }`: every lock but those kinds. A billing lock leaves the\n * reader able to remove access, revoke sessions, delete the account and change their\n * own settings (§3.3, §12.13), so the kit's parts for those take\n * {@link COMMIT_EXCEPT_BILLING} built in, and an app's own controls of that sort do\n * too.\n * - `false` or left out: no lock reaches it.\n *\n * Under a demo lock and a billing lock together, a control exempt from billing is\n * still refused, with the demo's reason.\n */\nexport type CommitScope = boolean | { readonly except: readonly WriteLockKind[] };\n\n/** Every lock but billing's: the scope of an action a lapsed plan still allows — removing\n * access, the account's own settings, an operator's admin route (§12.13). One constant,\n * so the call sites read alike. */\nexport const COMMIT_EXCEPT_BILLING = { except: [\"billing\"] } as const;\n\n/**\n * What {@link useWriteLock} returns: whether commits are locked here as a control with\n * the scope asked for sees it, and why.\n */\nexport interface WriteLock {\n locked: boolean;\n /** The one sentence a locked commit shows in its tooltip: the first hold in scope's.\n * Always set while `locked`; `undefined` when not. */\n reason: ReactNode | undefined;\n /** The first hold in scope's kind; `undefined` while unlocked, or for a source that\n * names none. */\n kind: WriteLockKind | undefined;\n /**\n * EVERY locked source the provider holds, in the order the server refuses them\n * (§12.3: the demo's 403 before billing's 402) — unfiltered by the scope, for code\n * that must know what else locks (a toast that names the plan, a swipe plan). Empty\n * while the provider is unlocked.\n */\n holds: readonly WriteLockHold[];\n}\n\nconst NO_HOLDS: readonly WriteLockHold[] = [];\n\nconst UNLOCKED: WriteLock = { locked: false, reason: undefined, kind: undefined, holds: NO_HOLDS };\n\nconst WriteLockContext = createContext<WriteLock>(UNLOCKED);\n\nexport interface WriteLockProviderProps {\n /** Commits below are locked. `false` unlocks a subtree under an outer lock. */\n locked: boolean;\n /**\n * The one sentence that says why — \"Shared with you to read\", \"Read-only demo —\n * saving is disabled\", \"A customer account cannot create curves\". The app's policy,\n * already translated. Left out: `labels.reason`.\n */\n reason?: ReactNode;\n /** What kind of lock this is — `\"demo\"`, `\"billing\"` or the app's own (see\n * {@link WriteLockKind}), for a provider of one source. Left out, no control can be\n * exempt from it. */\n kind?: WriteLockKind;\n /**\n * Every locked source, in refusal order — what `combineWriteLocks` answers, so\n * `<WriteLockProvider {...combineWriteLocks([...])}>` carries them. Given while\n * `locked`, it wins over `kind` and `reason`; a hold without a reason takes\n * `labels.reason`.\n */\n holds?: readonly WriteLockHold[];\n labels?: Partial<WriteLockLabels>;\n children?: ReactNode;\n}\n\n// `null`/`\"\"`/`false` count as \"no reason given\": a lock whose tooltip is empty would be\n// a disabled button that cannot say why, the thing this replaces.\nfunction given(reason: ReactNode): boolean {\n return reason !== undefined && reason !== null && reason !== false && reason !== \"\";\n}\n\n/**\n * The read-only lock — **everything renders; only the commit is locked.**\n *\n * keksdose (features/budgets/write-lock.tsx, the read-only demo budget) and\n * Kurvenschmiede (features/sharing/write-lock.tsx, a curve shared to view, a customer\n * account that owns nothing) each built the same `SaveGuard`: the page, its tabs,\n * forms and dialogs render exactly as for an owner, because a viewer looking at half\n * a page is not looking at what they were sent; what changes is that the control\n * that SAVES is off and says why on hover or focus. Both wrapped each Save in a\n * Tooltip and forced a native `disabled` on it — out of the tab order, so the reason\n * never reached a keyboard — and both had to remember it at thirty call sites.\n *\n * Here the page mounts one provider and each commit control opts in with `commit`\n * ({@link Button}, {@link IconButton}, {@link FormActions}): under a lock it takes the\n * kit's `disabledReason` path with this reason — `aria-disabled` and focusable,\n * every activation swallowed, the reason in the kit Tooltip and its description.\n *\n * Who is locked is the app's: the provider takes a boolean, never a role. Fields stay\n * editable — nothing in them reaches the server until the commit is pressed, and a\n * form you cannot fill in is not a demo of the form (keksdose accounts-page). A\n * control that IS its own commit (a toggle that saves on change) reads\n * {@link useWriteLock} and disables itself. The lock is a courtesy, not a guard: the\n * server still refuses the write.\n *\n * **A lock says its source** (0.33, docs/billing-harmonization.md §12.36). A lapsed\n * plan locks creating and changing, but not removing access or the account's own\n * settings (§3.3, §12.13), and the kit's parts for those hard-coded `commit` — so\n * kastlan's app-wide lock locked a member's own sign-out everywhere. Each source now\n * has a kind, the provider holds every locked one in order (`holds`, from\n * `combineWriteLocks`), and a control's `commit` may name the kinds it is exempt from\n * ({@link CommitScope}). The kit's parts follow §3.3 and §12.13 by themselves.\n *\n * Nested providers: the nearest wins, so an inner `locked={false}` reopens a section\n * the caller may write (a viewer's own notes on a shared curve) — every source at\n * once — and an inner lock with its own reason (Kurvenschmiede's owner lock beside the\n * viewer lock) overrides the outer one's sentence and its holds.\n */\nexport function WriteLockProvider({ locked, reason, kind, holds, labels, children }: WriteLockProviderProps) {\n // The `writeLock` namespace: prop > `<UiKitProvider labels>` > English.\n const fallback = useKitLabels(\"writeLock\", DEFAULT_WRITE_LOCK_LABELS, labels).reason;\n // `holds` wins while it has any; otherwise this provider is one source of its own.\n const several = locked && holds !== undefined && holds.length > 0 ? holds : undefined;\n const firstKind = several ? several[0].kind : kind;\n const firstGiven = several ? several[0].reason : reason;\n const firstReason = given(firstGiven) ? firstGiven : fallback;\n // Memoised on the first hold's kind and sentence — the strings an app passes — so a\n // one-source lock keeps one context value across renders; a list of several is\n // memoised on its own identity.\n const many = several && several.length > 1 ? several : undefined;\n const value = useMemo<WriteLock>(() => {\n if (!locked) return UNLOCKED;\n const all = many\n ? many.map((hold) => ({ kind: hold.kind, reason: given(hold.reason) ? hold.reason : fallback }))\n : [{ kind: firstKind, reason: firstReason }];\n return { locked: true, reason: firstReason, kind: firstKind, holds: all };\n }, [locked, many, firstKind, firstReason, fallback]);\n return <WriteLockContext.Provider value={value}>{children}</WriteLockContext.Provider>;\n}\n\n/**\n * Whether a hold refuses a control with this scope: `true` refuses with every hold,\n * `{ except }` with every hold whose kind it does not name. A hold with no kind is\n * never exempted — an app that forgot to name its source must not reopen by accident.\n */\nfunction inScope(hold: WriteLockHold, scope: CommitScope): boolean {\n if (scope === true) return true;\n if (scope === false) return false;\n return hold.kind === undefined || !scope.except.includes(hold.kind);\n}\n\n/**\n * The lock as a control with `scope` sees it — {@link useWriteLock}'s answer, pure, for\n * a scope known only at call time: `useConfirm` reads the CALLER's lock when it is\n * called, and applies each `confirm({ commit })`'s own scope to it when it runs.\n *\n * `undefined` and `false` see no lock (a control without `commit`); `true` sees the\n * lock as it is; `{ except }` sees the first hold of another kind, with its reason\n * and kind. `holds` is passed on unfiltered.\n */\nexport function writeLockFor(lock: WriteLock, scope: CommitScope | undefined): WriteLock {\n if (!lock.locked || scope === true) return lock;\n // A lock built by hand (a test's, an app's own context) may carry no holds: it is\n // then the one source it describes.\n const holds = lock.holds.length > 0 ? lock.holds : [{ kind: lock.kind, reason: lock.reason }];\n const first = scope === undefined ? undefined : holds.find((hold) => inScope(hold, scope));\n if (!first) return { ...UNLOCKED, holds: lock.holds };\n // The first in scope is the provider's own first: the lock as it is, same object.\n if (first === holds[0]) return lock;\n return { locked: true, reason: first.reason, kind: first.kind, holds: lock.holds };\n}\n\n/**\n * The nearest {@link WriteLockProvider}'s lock, as a control with `scope` sees it —\n * unlocked with no provider. Left out, the scope is `true`: every lock.\n *\n * For code that must KNOW rather than a control that opts in: a toast that says why,\n * a swipe plan that leaves an action out, a hand-rolled toggle that disables itself.\n * `useWriteLock(COMMIT_EXCEPT_BILLING)` answers \"would a lapsed plan's lock refuse me?\"\n * as a removal sees it — what keksdose's `useWriteLockKind() !== \"billing\"` asked.\n */\nexport function useWriteLock(scope: CommitScope = true): WriteLock {\n return writeLockFor(useContext(WriteLockContext), scope);\n}\n\n/**\n * The `disabledReason` a control with `commit` should use: the lock's reason while\n * the lock refuses this scope — it wins over the control's own, since it is the answer\n * to the question the hover is asking — else the control's own. Internal to the kit's\n * commit controls.\n */\nexport function useCommitReason(commit: CommitScope | undefined, own: ReactNode): ReactNode {\n const lock = writeLockFor(useContext(WriteLockContext), commit);\n return lock.locked ? lock.reason : own;\n}\n"],"mappings":";AAoKS;AApKT,SAAS,eAAe,YAAY,eAAe;AAEnD,SAAS,oBAAoB;AAQtB,MAAM,4BAA6C;AAAA,EACxD,QAAQ;AACV;AAqCO,MAAM,wBAAwB,EAAE,QAAQ,CAAC,SAAS,EAAE;AAuB3D,MAAM,WAAqC,CAAC;AAE5C,MAAM,WAAsB,EAAE,QAAQ,OAAO,QAAQ,QAAW,MAAM,QAAW,OAAO,SAAS;AAEjG,MAAM,mBAAmB,cAAyB,QAAQ;AA4B1D,SAAS,MAAM,QAA4B;AACzC,SAAO,WAAW,UAAa,WAAW,QAAQ,WAAW,SAAS,WAAW;AACnF;AAuCO,SAAS,kBAAkB,EAAE,QAAQ,QAAQ,MAAM,OAAO,QAAQ,SAAS,GAA2B;AAE3G,QAAM,WAAW,aAAa,aAAa,2BAA2B,MAAM,EAAE;AAE9E,QAAM,UAAU,UAAU,UAAU,UAAa,MAAM,SAAS,IAAI,QAAQ;AAC5E,QAAM,YAAY,UAAU,QAAQ,CAAC,EAAE,OAAO;AAC9C,QAAM,aAAa,UAAU,QAAQ,CAAC,EAAE,SAAS;AACjD,QAAM,cAAc,MAAM,UAAU,IAAI,aAAa;AAIrD,QAAM,OAAO,WAAW,QAAQ,SAAS,IAAI,UAAU;AACvD,QAAM,QAAQ,QAAmB,MAAM;AACrC,QAAI,CAAC,OAAQ,QAAO;AACpB,UAAM,MAAM,OACR,KAAK,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,MAAM,QAAQ,MAAM,KAAK,MAAM,IAAI,KAAK,SAAS,SAAS,EAAE,IAC7F,CAAC,EAAE,MAAM,WAAW,QAAQ,YAAY,CAAC;AAC7C,WAAO,EAAE,QAAQ,MAAM,QAAQ,aAAa,MAAM,WAAW,OAAO,IAAI;AAAA,EAC1E,GAAG,CAAC,QAAQ,MAAM,WAAW,aAAa,QAAQ,CAAC;AACnD,SAAO,oBAAC,iBAAiB,UAAjB,EAA0B,OAAe,UAAS;AAC5D;AAOA,SAAS,QAAQ,MAAqB,OAA6B;AACjE,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,UAAU,MAAO,QAAO;AAC5B,SAAO,KAAK,SAAS,UAAa,CAAC,MAAM,OAAO,SAAS,KAAK,IAAI;AACpE;AAWO,SAAS,aAAa,MAAiB,OAA2C;AACvF,MAAI,CAAC,KAAK,UAAU,UAAU,KAAM,QAAO;AAG3C,QAAM,QAAQ,KAAK,MAAM,SAAS,IAAI,KAAK,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,QAAQ,KAAK,OAAO,CAAC;AAC5F,QAAM,QAAQ,UAAU,SAAY,SAAY,MAAM,KAAK,CAAC,SAAS,QAAQ,MAAM,KAAK,CAAC;AACzF,MAAI,CAAC,MAAO,QAAO,EAAE,GAAG,UAAU,OAAO,KAAK,MAAM;AAEpD,MAAI,UAAU,MAAM,CAAC,EAAG,QAAO;AAC/B,SAAO,EAAE,QAAQ,MAAM,QAAQ,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO,KAAK,MAAM;AACnF;AAWO,SAAS,aAAa,QAAqB,MAAiB;AACjE,SAAO,aAAa,WAAW,gBAAgB,GAAG,KAAK;AACzD;AAQO,SAAS,gBAAgB,QAAiC,KAA2B;AAC1F,QAAM,OAAO,aAAa,WAAW,gBAAgB,GAAG,MAAM;AAC9D,SAAO,KAAK,SAAS,KAAK,SAAS;AACrC;","names":[]}
|
|
@@ -387,6 +387,23 @@ interface DataTableProps<T> {
|
|
|
387
387
|
rowHref?: (row: T) => string | undefined;
|
|
388
388
|
expandedRow?: (row: T) => ReactNode | null;
|
|
389
389
|
isExpanded?: (row: T) => boolean;
|
|
390
|
+
/**
|
|
391
|
+
* Extra classes for a row — the `<tr>` on desktop, the card on mobile. Merged last,
|
|
392
|
+
* so a `hover:` fill here replaces the row's own `hover:bg-[var(--bg-hover)]`.
|
|
393
|
+
*
|
|
394
|
+
* **A row you paint has to pick its own hover** (0.33, docs/colour-roles-harmonization.md
|
|
395
|
+
* §12.2): the kit cannot see your rest colour, and `--bg-hover` is mixed against the
|
|
396
|
+
* card. The rule: a hover differs from its rest by 1.08:1 or more, and every text role
|
|
397
|
+
* on it keeps 4.5:1.
|
|
398
|
+
* - A row that rests on the well (`bg-surface-2`) hovers to the CARD,
|
|
399
|
+
* `hover:bg-surface`: in light the well is the page, and `--bg-hover` sits 1.04:1
|
|
400
|
+
* from it.
|
|
401
|
+
* - A row whose well MARKS A STATE (selected) keeps its fill and draws a 1 px inside
|
|
402
|
+
* line instead, since the card would read as "not selected":
|
|
403
|
+
* `bg-surface-2 hover:bg-surface-2 hover:outline hover:-outline-offset-1 hover:outline-strong`.
|
|
404
|
+
* An outline, not a shadow: a shadow on a `<tr>` is not painted by every engine.
|
|
405
|
+
* - Not `--bg-active` for a selected row: its muted and money text fall to 3.8–4.7:1.
|
|
406
|
+
*/
|
|
390
407
|
rowClassName?: (row: T) => string | undefined;
|
|
391
408
|
/**
|
|
392
409
|
* Extra DOM attributes for a row's container — the `<tr>` on desktop, the
|
package/dist/data-table.d.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
export { C as ColumnFilter, D as DEFAULT_DATA_TABLE_LABELS, a as DEFAULT_DATA_TABLE_SORT_LABELS, b as DataTable, c as DataTableChrome, d as DataTableColumn, e as DataTableDensity, f as DataTableLabels, g as DataTableProps, h as DataTableRowAction, i as DataTableSortLabels, F as FilterState, j as FilterValue, M as MobileSwipeActions, S as ServerPagination, T as TableUrlState, k as TableUrlStateProps, l as TableUrlSync, U as UseTableUrlStateOptions, m as UseTableUrlStateReturn, n as dateFilter, o as decodeFilterValue, p as decodeFilterValueOfType, q as defaultFilterState, r as encodeFilterValue, s as filterHref, t as isFilterActive, u as missingDataTableLabels, v as numberFilter, w as readTableUrlState, x as resolveDataTableLabels, y as resolveFilter, z as rowMatches, A as selectFilter, B as textFilter, E as useTableUrlState } from './data-table-labels-
|
|
1
|
+
export { C as ColumnFilter, D as DEFAULT_DATA_TABLE_LABELS, a as DEFAULT_DATA_TABLE_SORT_LABELS, b as DataTable, c as DataTableChrome, d as DataTableColumn, e as DataTableDensity, f as DataTableLabels, g as DataTableProps, h as DataTableRowAction, i as DataTableSortLabels, F as FilterState, j as FilterValue, M as MobileSwipeActions, S as ServerPagination, T as TableUrlState, k as TableUrlStateProps, l as TableUrlSync, U as UseTableUrlStateOptions, m as UseTableUrlStateReturn, n as dateFilter, o as decodeFilterValue, p as decodeFilterValueOfType, q as defaultFilterState, r as encodeFilterValue, s as filterHref, t as isFilterActive, u as missingDataTableLabels, v as numberFilter, w as readTableUrlState, x as resolveDataTableLabels, y as resolveFilter, z as rowMatches, A as selectFilter, B as textFilter, E as useTableUrlState } from './data-table-labels-BJ5JE_X2.js';
|
|
2
2
|
export { SortCycle, SortDir, SortState, SortStepOptions, decodeSorts, encodeSorts, nextSorts, normalizeSorts } from './components/data-table-sort.js';
|
|
3
3
|
export { PAGE_SIZE_OPTIONS, Pagination } from './components/data-table-pagination.js';
|
|
4
4
|
export { FilterPopover } from './components/data-table-filter-popover.js';
|
|
5
5
|
export { BooleanColumnOptions, BooleanMark, BooleanMarkProps, booleanColumn } from './components/data-table-cells.js';
|
|
6
6
|
import 'react';
|
|
7
7
|
import './components/swipeable-row.js';
|
|
8
|
+
import './components/status-dot.js';
|
|
9
|
+
import './components/progress-bar.js';
|
|
10
|
+
import './components/signed-amount.js';
|
|
11
|
+
import './components/stat-tile.js';
|
|
12
|
+
import './components/chip.js';
|
|
13
|
+
import 'lucide-react';
|
|
14
|
+
import './components/field-parts.js';
|
|
15
|
+
import './components/tooltip.js';
|
|
16
|
+
import './hooks/use-anchored-rect.js';
|
|
17
|
+
import './lib/clipping.js';
|
|
18
|
+
import './components/write-lock.js';
|