@happyvertical/smrt-fields 0.40.60 → 0.40.62
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/AGENTS.md +58 -12
- package/README.md +143 -42
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/cache.d.ts +18 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/chunks/FieldPolicyCollection--RxukfCX.js +1218 -0
- package/dist/chunks/FieldPolicyCollection--RxukfCX.js.map +1 -0
- package/dist/collections/FieldPolicyCollection.d.ts +95 -0
- package/dist/collections/FieldPolicyCollection.d.ts.map +1 -0
- package/dist/collections/FieldPolicySuggestionCollection.d.ts +160 -0
- package/dist/collections/FieldPolicySuggestionCollection.d.ts.map +1 -0
- package/dist/collections/FieldUsageCounterCollection.d.ts +143 -0
- package/dist/collections/FieldUsageCounterCollection.d.ts.map +1 -0
- package/dist/deterministic-id.d.ts +18 -0
- package/dist/deterministic-id.d.ts.map +1 -0
- package/dist/field-definitions.d.ts +85 -0
- package/dist/field-definitions.d.ts.map +1 -0
- package/dist/field-policy-resolver.d.ts +46 -0
- package/dist/field-policy-resolver.d.ts.map +1 -0
- package/dist/index.d.ts +15 -532
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1813 -628
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +1487 -191
- package/dist/models/FieldPolicy.d.ts +163 -0
- package/dist/models/FieldPolicy.d.ts.map +1 -0
- package/dist/models/FieldPolicySuggestion.d.ts +132 -0
- package/dist/models/FieldPolicySuggestion.d.ts.map +1 -0
- package/dist/models/FieldUsageCounter.d.ts +178 -0
- package/dist/models/FieldUsageCounter.d.ts.map +1 -0
- package/dist/models/FieldUsageReportReceipt.d.ts +25 -0
- package/dist/models/FieldUsageReportReceipt.d.ts.map +1 -0
- package/dist/permissions.d.ts +9 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/playground.d.ts +2 -0
- package/dist/playground.d.ts.map +1 -0
- package/dist/playground.js +39 -0
- package/dist/playground.js.map +1 -0
- package/dist/settings-catalog.d.ts +73 -0
- package/dist/settings-catalog.d.ts.map +1 -0
- package/dist/smrt-knowledge.json +449 -9
- package/dist/svelte/__tests__/FieldPolicyControlPanel.test.js +277 -0
- package/dist/svelte/__tests__/FieldPolicyGear.test.js +503 -0
- package/dist/svelte/__tests__/FormHelp.test.js +138 -0
- package/dist/svelte/__tests__/ModeUX.test.js +109 -0
- package/dist/svelte/__tests__/ObjectForm.test.js +687 -0
- package/dist/svelte/__tests__/ObjectFormGeneratedApi.integration.test.js +436 -0
- package/dist/svelte/__tests__/PolicyField.test.js +373 -0
- package/dist/svelte/__tests__/UsageLearning.test.js +140 -0
- package/dist/svelte/__tests__/fixtures/AdvancedFieldsFixture.svelte +30 -0
- package/dist/svelte/__tests__/fixtures/AdvancedFieldsFixture.svelte.d.ts +9 -0
- package/dist/svelte/__tests__/fixtures/AdvancedFieldsFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/DomPrefillFixture.svelte +33 -0
- package/dist/svelte/__tests__/fixtures/DomPrefillFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/DomPrefillFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/FormHelpFixture.svelte +19 -0
- package/dist/svelte/__tests__/fixtures/FormHelpFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/FormHelpFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/GeneratedApiGearFixture.svelte +18 -0
- package/dist/svelte/__tests__/fixtures/GeneratedApiGearFixture.svelte.d.ts +11 -0
- package/dist/svelte/__tests__/fixtures/GeneratedApiGearFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/GracefulDegradeFixture.svelte +11 -0
- package/dist/svelte/__tests__/fixtures/GracefulDegradeFixture.svelte.d.ts +19 -0
- package/dist/svelte/__tests__/fixtures/GracefulDegradeFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ModeSwitchFixture.svelte +18 -0
- package/dist/svelte/__tests__/fixtures/ModeSwitchFixture.svelte.d.ts +8 -0
- package/dist/svelte/__tests__/fixtures/ModeSwitchFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/NoIdFixture.svelte +24 -0
- package/dist/svelte/__tests__/fixtures/NoIdFixture.svelte.d.ts +13 -0
- package/dist/svelte/__tests__/fixtures/NoIdFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte +37 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts +15 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormFixture.svelte +17 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormRegistryFixture.svelte +25 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormRegistryFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormRegistryFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSnippetFixture.svelte +34 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSnippetFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSnippetFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceFixture.svelte +29 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceFixture.svelte.d.ts +11 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceSnippetFixture.svelte +33 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceSnippetFixture.svelte.d.ts +9 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormSourceSnippetFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/PolicyDataTableFixture.svelte +40 -0
- package/dist/svelte/__tests__/fixtures/PolicyDataTableFixture.svelte.d.ts +8 -0
- package/dist/svelte/__tests__/fixtures/PolicyDataTableFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/PrefillFixture.svelte +26 -0
- package/dist/svelte/__tests__/fixtures/PrefillFixture.svelte.d.ts +13 -0
- package/dist/svelte/__tests__/fixtures/PrefillFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ProviderFieldFixture.svelte +39 -0
- package/dist/svelte/__tests__/fixtures/ProviderFieldFixture.svelte.d.ts +17 -0
- package/dist/svelte/__tests__/fixtures/ProviderFieldFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/RegistryInput.svelte +15 -0
- package/dist/svelte/__tests__/fixtures/RegistryInput.svelte.d.ts +5 -0
- package/dist/svelte/__tests__/fixtures/RegistryInput.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/RevealPrefillFixture.svelte +29 -0
- package/dist/svelte/__tests__/fixtures/RevealPrefillFixture.svelte.d.ts +14 -0
- package/dist/svelte/__tests__/fixtures/RevealPrefillFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/SettingsCatalogStub.svelte +24 -0
- package/dist/svelte/__tests__/fixtures/SettingsCatalogStub.svelte.d.ts +14 -0
- package/dist/svelte/__tests__/fixtures/SettingsCatalogStub.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/SnippetFixture.svelte +28 -0
- package/dist/svelte/__tests__/fixtures/SnippetFixture.svelte.d.ts +13 -0
- package/dist/svelte/__tests__/fixtures/SnippetFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/SuggestionGearFixture.svelte +23 -0
- package/dist/svelte/__tests__/fixtures/SuggestionGearFixture.svelte.d.ts +10 -0
- package/dist/svelte/__tests__/fixtures/SuggestionGearFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/ToggleModeButton.svelte +14 -0
- package/dist/svelte/__tests__/fixtures/ToggleModeButton.svelte.d.ts +19 -0
- package/dist/svelte/__tests__/fixtures/ToggleModeButton.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/fixtures/TooltipFixture.svelte +25 -0
- package/dist/svelte/__tests__/fixtures/TooltipFixture.svelte.d.ts +14 -0
- package/dist/svelte/__tests__/fixtures/TooltipFixture.svelte.d.ts.map +1 -0
- package/dist/svelte/__tests__/settings-catalog.test.js +161 -0
- package/dist/svelte/components/AdvancedFields.svelte +49 -0
- package/dist/svelte/components/AdvancedFields.svelte.d.ts +17 -0
- package/dist/svelte/components/AdvancedFields.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldInput.svelte +159 -0
- package/dist/svelte/components/FieldInput.svelte.d.ts +5 -0
- package/dist/svelte/components/FieldInput.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyControlPanel.svelte +288 -0
- package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts +29 -0
- package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyEditor.svelte +417 -0
- package/dist/svelte/components/FieldPolicyEditor.svelte.d.ts +18 -0
- package/dist/svelte/components/FieldPolicyEditor.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyGearButton.svelte +24 -0
- package/dist/svelte/components/FieldPolicyGearButton.svelte.d.ts +8 -0
- package/dist/svelte/components/FieldPolicyGearButton.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyGearProvider.svelte +169 -0
- package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts +20 -0
- package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicyProvider.svelte +89 -0
- package/dist/svelte/components/FieldPolicyProvider.svelte.d.ts +35 -0
- package/dist/svelte/components/FieldPolicyProvider.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FieldPolicySuggestionQueue.svelte +135 -0
- package/dist/svelte/components/FieldPolicySuggestionQueue.svelte.d.ts +11 -0
- package/dist/svelte/components/FieldPolicySuggestionQueue.svelte.d.ts.map +1 -0
- package/dist/svelte/components/FormHelp.svelte +157 -0
- package/dist/svelte/components/FormHelp.svelte.d.ts +15 -0
- package/dist/svelte/components/FormHelp.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ModeSwitch.svelte +47 -0
- package/dist/svelte/components/ModeSwitch.svelte.d.ts +10 -0
- package/dist/svelte/components/ModeSwitch.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ObjectForm.svelte +440 -0
- package/dist/svelte/components/ObjectForm.svelte.d.ts +50 -0
- package/dist/svelte/components/ObjectForm.svelte.d.ts.map +1 -0
- package/dist/svelte/components/ObjectFormSourceProvider.svelte +18 -0
- package/dist/svelte/components/ObjectFormSourceProvider.svelte.d.ts +11 -0
- package/dist/svelte/components/ObjectFormSourceProvider.svelte.d.ts.map +1 -0
- package/dist/svelte/components/PolicyField.svelte +338 -0
- package/dist/svelte/components/PolicyField.svelte.d.ts +80 -0
- package/dist/svelte/components/PolicyField.svelte.d.ts.map +1 -0
- package/dist/svelte/context.svelte.d.ts +54 -0
- package/dist/svelte/context.svelte.d.ts.map +1 -0
- package/dist/svelte/context.svelte.js +55 -0
- package/dist/svelte/data-table.d.ts +17 -0
- package/dist/svelte/data-table.d.ts.map +1 -0
- package/dist/svelte/data-table.js +19 -0
- package/dist/svelte/field-policy-editor.d.ts +81 -0
- package/dist/svelte/field-policy-editor.d.ts.map +1 -0
- package/dist/svelte/field-policy-editor.js +120 -0
- package/dist/svelte/gear-context.svelte.d.ts +16 -0
- package/dist/svelte/gear-context.svelte.d.ts.map +1 -0
- package/dist/svelte/gear-context.svelte.js +15 -0
- package/dist/svelte/index.d.ts +63 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +41 -0
- package/dist/svelte/input-registry.d.ts +21 -0
- package/dist/svelte/input-registry.d.ts.map +1 -0
- package/dist/svelte/input-registry.js +26 -0
- package/dist/svelte/object-form-source-context.svelte.d.ts +4 -0
- package/dist/svelte/object-form-source-context.svelte.d.ts.map +1 -0
- package/dist/svelte/object-form-source-context.svelte.js +8 -0
- package/dist/svelte/object-form-source.svelte.d.ts +18 -0
- package/dist/svelte/object-form-source.svelte.d.ts.map +1 -0
- package/dist/svelte/object-form-source.svelte.js +99 -0
- package/dist/svelte/object-form.d.ts +6 -0
- package/dist/svelte/object-form.d.ts.map +1 -0
- package/dist/svelte/object-form.js +38 -0
- package/dist/svelte/playground/FieldPolicyFormPreview.svelte +212 -0
- package/dist/svelte/playground/FieldPolicyFormPreview.svelte.d.ts +4 -0
- package/dist/svelte/playground/FieldPolicyFormPreview.svelte.d.ts.map +1 -0
- package/dist/svelte/playground/ObjectFormPreview.svelte +129 -0
- package/dist/svelte/playground/ObjectFormPreview.svelte.d.ts +4 -0
- package/dist/svelte/playground/ObjectFormPreview.svelte.d.ts.map +1 -0
- package/dist/svelte/playground.d.ts +20 -0
- package/dist/svelte/playground.d.ts.map +1 -0
- package/dist/svelte/playground.js +38 -0
- package/dist/svelte/settings-catalog.d.ts +54 -0
- package/dist/svelte/settings-catalog.d.ts.map +1 -0
- package/dist/svelte/settings-catalog.js +116 -0
- package/dist/svelte/suggestions.d.ts +38 -0
- package/dist/svelte/suggestions.d.ts.map +1 -0
- package/dist/svelte/suggestions.js +68 -0
- package/dist/svelte/types.d.ts +101 -0
- package/dist/svelte/types.d.ts.map +1 -0
- package/dist/svelte/types.js +4 -0
- package/dist/svelte/usage-capture.d.ts +63 -0
- package/dist/svelte/usage-capture.d.ts.map +1 -0
- package/dist/svelte/usage-capture.js +61 -0
- package/dist/types.d.ts +316 -203
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -1
- package/dist/types.js.map +1 -1
- package/dist/usage-learning.d.ts +201 -0
- package/dist/usage-learning.d.ts.map +1 -0
- package/dist/usage-schedules.d.ts +110 -0
- package/dist/usage-schedules.d.ts.map +1 -0
- package/dist/users-module.d.ts +30 -0
- package/dist/users-module.d.ts.map +1 -0
- package/package.json +33 -8
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test fixture: an advanced-tier PolicyField with a resolved default that is
|
|
3
|
+
* hidden at mount (basic mode) and revealed by the mode toggle. Verifies
|
|
4
|
+
* prefill runs on first reveal, not only at mount.
|
|
5
|
+
*/
|
|
6
|
+
import type { ResolvedObjectFieldPolicy } from '../../../types.js';
|
|
7
|
+
type $$ComponentProps = {
|
|
8
|
+
policy: ResolvedObjectFieldPolicy;
|
|
9
|
+
isNewRecord?: boolean;
|
|
10
|
+
};
|
|
11
|
+
declare const RevealPrefillFixture: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
|
+
type RevealPrefillFixture = ReturnType<typeof RevealPrefillFixture>;
|
|
13
|
+
export default RevealPrefillFixture;
|
|
14
|
+
//# sourceMappingURL=RevealPrefillFixture.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RevealPrefillFixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/__tests__/fixtures/RevealPrefillFixture.svelte.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAKlE,KAAK,gBAAgB,GAAI;IACxB,MAAM,EAAE,yBAAyB,CAAC;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AA0BF,QAAA,MAAM,oBAAoB,sDAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type {
|
|
4
|
+
FieldPolicyDetailItem,
|
|
5
|
+
FieldPolicySettingsCatalogPage,
|
|
6
|
+
} from '../../../settings-catalog.js';
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
page: FieldPolicySettingsCatalogPage;
|
|
10
|
+
baseUrl: string;
|
|
11
|
+
detail: Snippet<[{ item: FieldPolicyDetailItem }]>;
|
|
12
|
+
preservedParams?: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
let { page, baseUrl, detail, preservedParams = {} }: Props = $props();
|
|
16
|
+
const href = $derived(
|
|
17
|
+
`${baseUrl}?${new URLSearchParams(preservedParams).toString()}`,
|
|
18
|
+
);
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<a aria-label="catalog navigation" {href}>Catalog navigation</a>
|
|
22
|
+
{#if page.selected}
|
|
23
|
+
{@render detail({ item: page.selected })}
|
|
24
|
+
{/if}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { FieldPolicyDetailItem, FieldPolicySettingsCatalogPage } from '../../../settings-catalog.js';
|
|
3
|
+
interface Props {
|
|
4
|
+
page: FieldPolicySettingsCatalogPage;
|
|
5
|
+
baseUrl: string;
|
|
6
|
+
detail: Snippet<[{
|
|
7
|
+
item: FieldPolicyDetailItem;
|
|
8
|
+
}]>;
|
|
9
|
+
preservedParams?: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
declare const SettingsCatalogStub: import("svelte").Component<Props, {}, "">;
|
|
12
|
+
type SettingsCatalogStub = ReturnType<typeof SettingsCatalogStub>;
|
|
13
|
+
export default SettingsCatalogStub;
|
|
14
|
+
//# sourceMappingURL=SettingsCatalogStub.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SettingsCatalogStub.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/__tests__/fixtures/SettingsCatalogStub.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,KAAK,EACV,qBAAqB,EACrB,8BAA8B,EAC/B,MAAM,8BAA8B,CAAC;AAGtC,UAAU,KAAK;IACb,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,OAAO,CAAC,CAAC;QAAE,IAAI,EAAE,qBAAqB,CAAA;KAAE,CAAC,CAAC,CAAC;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAmBD,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Test fixture: PolicyField snippet escape hatch with full policy data.
|
|
4
|
+
* Verifies the snippet receives resolved label, help, required, etc.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { ResolvedObjectFieldPolicy } from '../../../types.js';
|
|
8
|
+
import FieldPolicyProvider from '../../components/FieldPolicyProvider.svelte';
|
|
9
|
+
import PolicyField from '../../components/PolicyField.svelte';
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
policy,
|
|
13
|
+
mode = 'basic',
|
|
14
|
+
}: {
|
|
15
|
+
policy: ResolvedObjectFieldPolicy;
|
|
16
|
+
mode?: 'basic' | 'advanced';
|
|
17
|
+
} = $props();
|
|
18
|
+
</script>
|
|
19
|
+
|
|
20
|
+
<FieldPolicyProvider {policy} {mode}>
|
|
21
|
+
<PolicyField name="name">
|
|
22
|
+
{#snippet render({ label, help, required })}
|
|
23
|
+
<div data-testid="field-label">{label}</div>
|
|
24
|
+
<div data-testid="field-help">{help}</div>
|
|
25
|
+
<div data-testid="field-required">{String(required)}</div>
|
|
26
|
+
{/snippet}
|
|
27
|
+
</PolicyField>
|
|
28
|
+
</FieldPolicyProvider>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test fixture: PolicyField snippet escape hatch with full policy data.
|
|
3
|
+
* Verifies the snippet receives resolved label, help, required, etc.
|
|
4
|
+
*/
|
|
5
|
+
import type { ResolvedObjectFieldPolicy } from '../../../types.js';
|
|
6
|
+
type $$ComponentProps = {
|
|
7
|
+
policy: ResolvedObjectFieldPolicy;
|
|
8
|
+
mode?: 'basic' | 'advanced';
|
|
9
|
+
};
|
|
10
|
+
declare const SnippetFixture: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
11
|
+
type SnippetFixture = ReturnType<typeof SnippetFixture>;
|
|
12
|
+
export default SnippetFixture;
|
|
13
|
+
//# sourceMappingURL=SnippetFixture.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SnippetFixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/__tests__/fixtures/SnippetFixture.svelte.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAIlE,KAAK,gBAAgB,GAAI;IACxB,MAAM,EAAE,yBAAyB,CAAC;IAClC,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;CAC7B,CAAC;AA0BF,QAAA,MAAM,cAAc,sDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import FieldPolicyGearButton from '../../components/FieldPolicyGearButton.svelte';
|
|
3
|
+
import FieldPolicyGearProvider from '../../components/FieldPolicyGearProvider.svelte';
|
|
4
|
+
import type { FieldPolicyEditorAdapter } from '../../field-policy-editor.js';
|
|
5
|
+
import type { FieldPolicySuggestionAdapter } from '../../suggestions.js';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
adapter,
|
|
9
|
+
suggestionAdapter,
|
|
10
|
+
}: {
|
|
11
|
+
adapter: FieldPolicyEditorAdapter;
|
|
12
|
+
suggestionAdapter: FieldPolicySuggestionAdapter;
|
|
13
|
+
} = $props();
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<FieldPolicyGearProvider
|
|
17
|
+
objectRef="@test:Widget"
|
|
18
|
+
fields={{ title: { type: 'text' } }}
|
|
19
|
+
{adapter}
|
|
20
|
+
{suggestionAdapter}
|
|
21
|
+
>
|
|
22
|
+
<FieldPolicyGearButton />
|
|
23
|
+
</FieldPolicyGearProvider>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FieldPolicyEditorAdapter } from '../../field-policy-editor.js';
|
|
2
|
+
import type { FieldPolicySuggestionAdapter } from '../../suggestions.js';
|
|
3
|
+
type $$ComponentProps = {
|
|
4
|
+
adapter: FieldPolicyEditorAdapter;
|
|
5
|
+
suggestionAdapter: FieldPolicySuggestionAdapter;
|
|
6
|
+
};
|
|
7
|
+
declare const SuggestionGearFixture: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
8
|
+
type SuggestionGearFixture = ReturnType<typeof SuggestionGearFixture>;
|
|
9
|
+
export default SuggestionGearFixture;
|
|
10
|
+
//# sourceMappingURL=SuggestionGearFixture.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SuggestionGearFixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/__tests__/fixtures/SuggestionGearFixture.svelte.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,8BAA8B,CAAC;AAC7E,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAExE,KAAK,gBAAgB,GAAI;IACxB,OAAO,EAAE,wBAAwB,CAAC;IAClC,iBAAiB,EAAE,4BAA4B,CAAC;CACjD,CAAC;AAmBF,QAAA,MAAM,qBAAqB,sDAAwC,CAAC;AACpE,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACtE,eAAe,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Test helper: a button rendered inside a FieldPolicyProvider that toggles
|
|
4
|
+
* the provider's mode state. Captures the context during component
|
|
5
|
+
* initialisation (getContext is only valid there in Svelte 5).
|
|
6
|
+
*/
|
|
7
|
+
import { getFieldPolicyContext } from '../../context.svelte.js';
|
|
8
|
+
|
|
9
|
+
const context = getFieldPolicyContext();
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<button onclick={() => context.mode.toggle()}>
|
|
13
|
+
Toggle Mode
|
|
14
|
+
</button>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
|
|
2
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
3
|
+
$$bindings?: Bindings;
|
|
4
|
+
} & Exports;
|
|
5
|
+
(internal: unknown, props: {
|
|
6
|
+
$$events?: Events;
|
|
7
|
+
$$slots?: Slots;
|
|
8
|
+
}): Exports & {
|
|
9
|
+
$set?: any;
|
|
10
|
+
$on?: any;
|
|
11
|
+
};
|
|
12
|
+
z_$$bindings?: Bindings;
|
|
13
|
+
}
|
|
14
|
+
declare const ToggleModeButton: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type ToggleModeButton = InstanceType<typeof ToggleModeButton>;
|
|
18
|
+
export default ToggleModeButton;
|
|
19
|
+
//# sourceMappingURL=ToggleModeButton.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToggleModeButton.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/__tests__/fixtures/ToggleModeButton.svelte.ts"],"names":[],"mappings":"AAuBA,UAAU,kCAAkC,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,GAAG,EAAE,OAAO,GAAG,EAAE,EAAE,QAAQ,GAAG,MAAM;IACpM,KAAK,OAAO,EAAE,OAAO,QAAQ,EAAE,2BAA2B,CAAC,KAAK,CAAC,GAAG,OAAO,QAAQ,EAAE,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,GAAG;QAAE,UAAU,CAAC,EAAE,QAAQ,CAAA;KAAE,GAAG,OAAO,CAAC;IACjK,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,KAAK,CAAA;KAAC,GAAG,OAAO,GAAG;QAAE,IAAI,CAAC,EAAE,GAAG,CAAC;QAAC,GAAG,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IACtG,YAAY,CAAC,EAAE,QAAQ,CAAC;CAC3B;AAKD,QAAA,MAAM,gBAAgB;;kBAA+E,CAAC;AACpF,KAAK,gBAAgB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAChE,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Test fixture: PolicyField with helpDensity='tooltip' to verify the help
|
|
4
|
+
* text attaches to the label as a title attribute instead of rendering a
|
|
5
|
+
* visible hint.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { ResolvedObjectFieldPolicy } from '../../../types.js';
|
|
9
|
+
import FieldPolicyProvider from '../../components/FieldPolicyProvider.svelte';
|
|
10
|
+
import PolicyField from '../../components/PolicyField.svelte';
|
|
11
|
+
|
|
12
|
+
let {
|
|
13
|
+
policy,
|
|
14
|
+
helpDensity = 'tooltip',
|
|
15
|
+
}: {
|
|
16
|
+
policy: ResolvedObjectFieldPolicy;
|
|
17
|
+
helpDensity?: 'hint' | 'tooltip';
|
|
18
|
+
} = $props();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<FieldPolicyProvider {policy} mode="basic">
|
|
22
|
+
<PolicyField name="name" {helpDensity}>
|
|
23
|
+
<input id="name" name="name" type="text" />
|
|
24
|
+
</PolicyField>
|
|
25
|
+
</FieldPolicyProvider>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test fixture: PolicyField with helpDensity='tooltip' to verify the help
|
|
3
|
+
* text attaches to the label as a title attribute instead of rendering a
|
|
4
|
+
* visible hint.
|
|
5
|
+
*/
|
|
6
|
+
import type { ResolvedObjectFieldPolicy } from '../../../types.js';
|
|
7
|
+
type $$ComponentProps = {
|
|
8
|
+
policy: ResolvedObjectFieldPolicy;
|
|
9
|
+
helpDensity?: 'hint' | 'tooltip';
|
|
10
|
+
};
|
|
11
|
+
declare const TooltipFixture: import("svelte").Component<$$ComponentProps, {}, "">;
|
|
12
|
+
type TooltipFixture = ReturnType<typeof TooltipFixture>;
|
|
13
|
+
export default TooltipFixture;
|
|
14
|
+
//# sourceMappingURL=TooltipFixture.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TooltipFixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/__tests__/fixtures/TooltipFixture.svelte.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAIlE,KAAK,gBAAgB,GAAI;IACxB,MAAM,EAAE,yBAAyB,CAAC;IAClC,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAClC,CAAC;AAsBF,QAAA,MAAM,cAAc,sDAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { auditObjectRefs, decorateCatalogPage, fieldPolicyCatalogPreservedParams, fieldPolicyControlPanelNavItem, fieldPolicyRollup, orgRowIdsForObject, prunableDriftRows, } from '../settings-catalog.js';
|
|
3
|
+
const objectRef = '@test/smrt-fields:Document';
|
|
4
|
+
function audit() {
|
|
5
|
+
return {
|
|
6
|
+
caller: {
|
|
7
|
+
tenantId: 'tenant',
|
|
8
|
+
userId: 'user',
|
|
9
|
+
canManageOrg: true,
|
|
10
|
+
canPersonalize: true,
|
|
11
|
+
},
|
|
12
|
+
appRows: [],
|
|
13
|
+
orgRows: [
|
|
14
|
+
{
|
|
15
|
+
id: 'org-row',
|
|
16
|
+
objectRef,
|
|
17
|
+
fieldName: 'title',
|
|
18
|
+
scopeType: 'tenant',
|
|
19
|
+
tenantId: 'tenant',
|
|
20
|
+
userId: null,
|
|
21
|
+
updatedBy: 'user',
|
|
22
|
+
createdAt: null,
|
|
23
|
+
updatedAt: null,
|
|
24
|
+
defaultValue: null,
|
|
25
|
+
displayOrder: null,
|
|
26
|
+
help: null,
|
|
27
|
+
label: null,
|
|
28
|
+
locked: null,
|
|
29
|
+
visibility: 'advanced',
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
inheritedOrgKeys: {},
|
|
33
|
+
userOverrideCounts: { [objectRef]: { title: 2 } },
|
|
34
|
+
driftRows: [
|
|
35
|
+
{
|
|
36
|
+
id: 'stale',
|
|
37
|
+
objectRef: '@gone:Old',
|
|
38
|
+
fieldName: 'gone',
|
|
39
|
+
scopeType: 'tenant',
|
|
40
|
+
tenantId: 'tenant',
|
|
41
|
+
userId: null,
|
|
42
|
+
updatedBy: null,
|
|
43
|
+
createdAt: null,
|
|
44
|
+
updatedAt: null,
|
|
45
|
+
reason: 'unknown-object',
|
|
46
|
+
prunable: true,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
policies: {
|
|
50
|
+
[objectRef]: {
|
|
51
|
+
objectRef,
|
|
52
|
+
fields: {
|
|
53
|
+
title: {
|
|
54
|
+
fieldName: 'title',
|
|
55
|
+
hasDefault: true,
|
|
56
|
+
defaultValue: 'tenant',
|
|
57
|
+
visibility: 'advanced',
|
|
58
|
+
help: null,
|
|
59
|
+
label: null,
|
|
60
|
+
order: null,
|
|
61
|
+
group: null,
|
|
62
|
+
locked: false,
|
|
63
|
+
required: false,
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
layers: {
|
|
67
|
+
title: [
|
|
68
|
+
{
|
|
69
|
+
layer: 'code',
|
|
70
|
+
delta: { default: { value: 'code' }, visibility: 'basic' },
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
layer: 'tenant',
|
|
74
|
+
tenantId: 'tenant',
|
|
75
|
+
delta: { default: { value: 'tenant' }, visibility: 'advanced' },
|
|
76
|
+
},
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
describe('field-policy control-panel adapters', () => {
|
|
84
|
+
it('replays explained layers for code/app/org cells and never exposes user rows', () => {
|
|
85
|
+
const rollup = fieldPolicyRollup(audit(), objectRef, 'title');
|
|
86
|
+
expect(rollup.code).toMatchObject({
|
|
87
|
+
defaultValue: 'code',
|
|
88
|
+
visibility: 'basic',
|
|
89
|
+
});
|
|
90
|
+
expect(rollup.org).toMatchObject({
|
|
91
|
+
defaultValue: 'tenant',
|
|
92
|
+
visibility: 'advanced',
|
|
93
|
+
contributed: true,
|
|
94
|
+
});
|
|
95
|
+
expect(rollup.userCount).toBe(2);
|
|
96
|
+
expect(rollup.orgRow?.id).toBe('org-row');
|
|
97
|
+
});
|
|
98
|
+
it('keeps a selected off-page object in the capped policy read while count refs remain complete', () => {
|
|
99
|
+
const page = {
|
|
100
|
+
items: Array.from({ length: 100 }, (_, index) => ({
|
|
101
|
+
objectRef: `@test:Thing${index}`,
|
|
102
|
+
})),
|
|
103
|
+
selected: { objectRef: '@test:Selected' },
|
|
104
|
+
};
|
|
105
|
+
const refs = auditObjectRefs(page);
|
|
106
|
+
expect(refs.objectRefs).toHaveLength(100);
|
|
107
|
+
expect(refs.objectRefs[0]).toBe('@test:Selected');
|
|
108
|
+
expect(refs.countObjectRefs).toHaveLength(101);
|
|
109
|
+
});
|
|
110
|
+
it('decorates an off-page selected detail alongside page summaries', () => {
|
|
111
|
+
const page = decorateCatalogPage({
|
|
112
|
+
items: [],
|
|
113
|
+
selected: {
|
|
114
|
+
id: 'selected',
|
|
115
|
+
objectRef,
|
|
116
|
+
fieldName: 'title',
|
|
117
|
+
className: 'Document',
|
|
118
|
+
packageName: '@test/smrt-fields',
|
|
119
|
+
label: 'Raw title',
|
|
120
|
+
description: 'Raw description',
|
|
121
|
+
fields: {},
|
|
122
|
+
},
|
|
123
|
+
query: '',
|
|
124
|
+
page: 1,
|
|
125
|
+
pageSize: 25,
|
|
126
|
+
total: 1,
|
|
127
|
+
}, audit());
|
|
128
|
+
expect(page.selected).toMatchObject({
|
|
129
|
+
label: 'Title',
|
|
130
|
+
status: 'Organization · 2 user overrides',
|
|
131
|
+
fields: {},
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
it('selects only caller-prunable drift rows and produces a permission-gated tenant nav item', () => {
|
|
135
|
+
expect(prunableDriftRows(audit()).map((row) => row.id)).toEqual(['stale']);
|
|
136
|
+
expect(orgRowIdsForObject(audit(), objectRef)).toEqual(['org-row']);
|
|
137
|
+
expect(fieldPolicyControlPanelNavItem({
|
|
138
|
+
href: '/admin/fields',
|
|
139
|
+
permissions: [],
|
|
140
|
+
})).toBeNull();
|
|
141
|
+
expect(fieldPolicyControlPanelNavItem({
|
|
142
|
+
href: '/admin/fields',
|
|
143
|
+
permissions: ['fields.policy.manage'],
|
|
144
|
+
})).toMatchObject({ href: '/admin/fields', label: 'Field settings' });
|
|
145
|
+
});
|
|
146
|
+
it('keeps a nondefault page size across catalog search, selection, and pagination links', () => {
|
|
147
|
+
expect(fieldPolicyCatalogPreservedParams({
|
|
148
|
+
page: { pageSize: 25 },
|
|
149
|
+
filters: {
|
|
150
|
+
packageFilter: 'package',
|
|
151
|
+
objectFilter: 'object',
|
|
152
|
+
customizedOnly: true,
|
|
153
|
+
},
|
|
154
|
+
})).toEqual({
|
|
155
|
+
package: 'package',
|
|
156
|
+
object: 'object',
|
|
157
|
+
customized: '1',
|
|
158
|
+
pageSize: '25',
|
|
159
|
+
});
|
|
160
|
+
});
|
|
161
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* AdvancedFields — a disclosure section for advanced-tier fields.
|
|
4
|
+
*
|
|
5
|
+
* An optional composition that wraps PolicyField-wrapped advanced fields. Uses
|
|
6
|
+
* `@happyvertical/smrt-ui/ui`'s Disclosure (native `<details>/<summary>` —
|
|
7
|
+
* good a11y baseline). The title shows the advanced field count from the
|
|
8
|
+
* resolved policy.
|
|
9
|
+
*
|
|
10
|
+
* The disclosure's open state is **not** coupled to the provider's mode: the
|
|
11
|
+
* mode determines *visibility* (advanced fields are hidden in basic mode),
|
|
12
|
+
* while the disclosure provides a *collapsed* view of those same fields when
|
|
13
|
+
* they are visible (advanced mode). Consumers who prefer the mode toggle alone
|
|
14
|
+
* (ModeSwitch) do not need this component.
|
|
15
|
+
*
|
|
16
|
+
* Must be used inside a FieldPolicyProvider.
|
|
17
|
+
*/
|
|
18
|
+
import { Disclosure } from '@happyvertical/smrt-ui/ui';
|
|
19
|
+
import type { Snippet } from 'svelte';
|
|
20
|
+
import { getFieldPolicyContext } from '../context.svelte.js';
|
|
21
|
+
|
|
22
|
+
export interface Props {
|
|
23
|
+
/**
|
|
24
|
+
* Title for the disclosure. Defaults to "Advanced" with the field count.
|
|
25
|
+
*/
|
|
26
|
+
title?: string;
|
|
27
|
+
/** Whether the disclosure starts open. */
|
|
28
|
+
open?: boolean;
|
|
29
|
+
/** Children — the advanced fields to render inside the disclosure. */
|
|
30
|
+
children?: Snippet;
|
|
31
|
+
/** Additional class. */
|
|
32
|
+
class?: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
let { title, open = false, children, class: className = '' }: Props = $props();
|
|
36
|
+
|
|
37
|
+
const context = getFieldPolicyContext();
|
|
38
|
+
|
|
39
|
+
const resolvedTitle = $derived(
|
|
40
|
+
title ??
|
|
41
|
+
`Advanced · ${context.advancedFieldCount} field${context.advancedFieldCount === 1 ? '' : 's'}`,
|
|
42
|
+
);
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
{#if context.mode.current === 'advanced' && context.advancedFieldCount > 0}
|
|
46
|
+
<Disclosure title={resolvedTitle} {open} class={className}>
|
|
47
|
+
{@render children?.()}
|
|
48
|
+
</Disclosure>
|
|
49
|
+
{/if}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
export interface Props {
|
|
3
|
+
/**
|
|
4
|
+
* Title for the disclosure. Defaults to "Advanced" with the field count.
|
|
5
|
+
*/
|
|
6
|
+
title?: string;
|
|
7
|
+
/** Whether the disclosure starts open. */
|
|
8
|
+
open?: boolean;
|
|
9
|
+
/** Children — the advanced fields to render inside the disclosure. */
|
|
10
|
+
children?: Snippet;
|
|
11
|
+
/** Additional class. */
|
|
12
|
+
class?: string;
|
|
13
|
+
}
|
|
14
|
+
declare const AdvancedFields: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type AdvancedFields = ReturnType<typeof AdvancedFields>;
|
|
16
|
+
export default AdvancedFields;
|
|
17
|
+
//# sourceMappingURL=AdvancedFields.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AdvancedFields.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/AdvancedFields.svelte.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAItC,MAAM,WAAW,KAAK;IACpB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0CAA0C;IAC1C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,sEAAsE;IACtE,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA0BD,QAAA,MAAM,cAAc,2CAAwC,CAAC;AAC7D,KAAK,cAAc,GAAG,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC;AACxD,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
/** Provider-free built-in adapters for the SMRT generated wire field types. */
|
|
3
|
+
import { Input, Textarea, Toggle } from '@happyvertical/smrt-ui/forms';
|
|
4
|
+
import { onDestroy } from 'svelte';
|
|
5
|
+
import type { FieldInputProps } from '../types.js';
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
id,
|
|
9
|
+
name,
|
|
10
|
+
label,
|
|
11
|
+
field,
|
|
12
|
+
value,
|
|
13
|
+
required,
|
|
14
|
+
disabled,
|
|
15
|
+
onvaluechange,
|
|
16
|
+
onvaliditychange,
|
|
17
|
+
}: FieldInputProps = $props();
|
|
18
|
+
|
|
19
|
+
let jsonText = $state('');
|
|
20
|
+
let jsonError = $state<string | null>(null);
|
|
21
|
+
|
|
22
|
+
onDestroy(() => {
|
|
23
|
+
// A hidden/unmounted invalid JSON control must not leave its parent form
|
|
24
|
+
// permanently blocked after a mode change.
|
|
25
|
+
if (jsonError) onvaliditychange?.(true);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
function formatJson(next: unknown): string {
|
|
29
|
+
if (next === undefined || next === null) return '';
|
|
30
|
+
return JSON.stringify(next, null, 2);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
$effect(() => {
|
|
34
|
+
// Keep external record updates visible, but never overwrite an invalid JSON
|
|
35
|
+
// draft while the user is correcting it. Compare serialized text rather than
|
|
36
|
+
// object identity: callers may pass a fresh record object each render.
|
|
37
|
+
if (jsonError) return;
|
|
38
|
+
const next = formatJson(value);
|
|
39
|
+
if (jsonText !== next) jsonText = next;
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
function setText(event: Event): void {
|
|
43
|
+
onvaluechange((event.currentTarget as HTMLInputElement).value);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function setNumber(event: Event, integer: boolean): void {
|
|
47
|
+
const input = event.currentTarget as HTMLInputElement;
|
|
48
|
+
// Browsers report incomplete number text (for example a lone sign or an
|
|
49
|
+
// unfinished exponent) as `value === ''` plus `badInput`. That is not a
|
|
50
|
+
// deliberate clear, so leave the record untouched until the edit is valid.
|
|
51
|
+
if (input.validity.badInput) return;
|
|
52
|
+
const raw = input.value;
|
|
53
|
+
if (raw === '') {
|
|
54
|
+
onvaluechange(undefined);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const number = Number(raw);
|
|
58
|
+
// Number inputs can transiently contain incomplete exponent/sign text while
|
|
59
|
+
// editing. Keep the last valid record value until the browser supplies a
|
|
60
|
+
// finite number; never leak NaN/Infinity into a create or edit payload.
|
|
61
|
+
if (!Number.isFinite(number)) return;
|
|
62
|
+
onvaluechange(integer ? Math.trunc(number) : number);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function setJson(event: Event): void {
|
|
66
|
+
jsonText = (event.currentTarget as HTMLTextAreaElement).value;
|
|
67
|
+
if (jsonText.trim() === '') {
|
|
68
|
+
jsonError = null;
|
|
69
|
+
onvaliditychange?.(true);
|
|
70
|
+
onvaluechange(undefined);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const parsed = JSON.parse(jsonText);
|
|
75
|
+
jsonError = null;
|
|
76
|
+
onvaliditychange?.(true);
|
|
77
|
+
onvaluechange(parsed);
|
|
78
|
+
} catch {
|
|
79
|
+
jsonError = 'Enter valid JSON before submitting this form.';
|
|
80
|
+
onvaliditychange?.(false);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function formatDateTimeLocal(value: unknown): string {
|
|
85
|
+
const date = value instanceof Date ? value : new Date(String(value));
|
|
86
|
+
if (Number.isNaN(date.getTime())) return '';
|
|
87
|
+
const part = (number: number) => String(number).padStart(2, '0');
|
|
88
|
+
return `${date.getFullYear()}-${part(date.getMonth() + 1)}-${part(date.getDate())}T${part(date.getHours())}:${part(date.getMinutes())}`;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function setDateTime(event: Event): void {
|
|
92
|
+
const raw = (event.currentTarget as HTMLInputElement).value;
|
|
93
|
+
if (!raw) {
|
|
94
|
+
onvaluechange(undefined);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const date = new Date(raw);
|
|
98
|
+
onvaluechange(Number.isNaN(date.getTime()) ? raw : date.toISOString());
|
|
99
|
+
}
|
|
100
|
+
</script>
|
|
101
|
+
|
|
102
|
+
{#if field.definition.type === 'boolean'}
|
|
103
|
+
<Toggle
|
|
104
|
+
{id}
|
|
105
|
+
{name}
|
|
106
|
+
checked={value === true}
|
|
107
|
+
{disabled}
|
|
108
|
+
ariaLabel={label ?? name}
|
|
109
|
+
onchange={onvaluechange}
|
|
110
|
+
/>
|
|
111
|
+
{:else if field.definition.type === 'json'}
|
|
112
|
+
<Textarea
|
|
113
|
+
{id}
|
|
114
|
+
{name}
|
|
115
|
+
value={jsonText}
|
|
116
|
+
{disabled}
|
|
117
|
+
{required}
|
|
118
|
+
rows={8}
|
|
119
|
+
aria-invalid={jsonError ? 'true' : undefined}
|
|
120
|
+
aria-describedby={jsonError ? `${id}-json-error` : undefined}
|
|
121
|
+
oninput={setJson}
|
|
122
|
+
/>
|
|
123
|
+
{#if jsonError}
|
|
124
|
+
<p id={`${id}-json-error`} class="field-input__error" role="alert">{jsonError}</p>
|
|
125
|
+
{/if}
|
|
126
|
+
{:else if field.definition.type === 'integer' || field.definition.type === 'decimal'}
|
|
127
|
+
<Input
|
|
128
|
+
{id}
|
|
129
|
+
{name}
|
|
130
|
+
type="number"
|
|
131
|
+
step={field.definition.type === 'integer' ? '1' : 'any'}
|
|
132
|
+
value={typeof value === 'number' ? value : ''}
|
|
133
|
+
{disabled}
|
|
134
|
+
{required}
|
|
135
|
+
oninput={(event: Event) => setNumber(event, field.definition.type === 'integer')}
|
|
136
|
+
/>
|
|
137
|
+
{:else if field.definition.type === 'datetime'}
|
|
138
|
+
<Input
|
|
139
|
+
{id}
|
|
140
|
+
{name}
|
|
141
|
+
type="datetime-local"
|
|
142
|
+
value={formatDateTimeLocal(value)}
|
|
143
|
+
{disabled}
|
|
144
|
+
{required}
|
|
145
|
+
oninput={setDateTime}
|
|
146
|
+
/>
|
|
147
|
+
{:else}
|
|
148
|
+
<Input
|
|
149
|
+
{id}
|
|
150
|
+
{name}
|
|
151
|
+
type="text"
|
|
152
|
+
value={typeof value === 'string' ? value : ''}
|
|
153
|
+
{disabled}
|
|
154
|
+
{required}
|
|
155
|
+
oninput={setText}
|
|
156
|
+
/>
|
|
157
|
+
{/if}
|
|
158
|
+
|
|
159
|
+
<style>.field-input__error { color: var(--smrt-color-error, #b42318); margin: 0; }</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FieldInput.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FieldInput.svelte.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AA0HnD,QAAA,MAAM,UAAU,qDAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
|