@happyvertical/smrt-fields 0.40.61 → 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/README.md +125 -112
- package/dist/chunks/FieldPolicyCollection--RxukfCX.js +1218 -0
- package/dist/chunks/FieldPolicyCollection--RxukfCX.js.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 +8 -0
- package/dist/field-definitions.d.ts.map +1 -1
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1565 -1077
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +1442 -188
- 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/smrt-knowledge.json +402 -5
- package/dist/svelte/__tests__/FieldPolicyControlPanel.test.js +54 -0
- package/dist/svelte/__tests__/ObjectForm.test.js +131 -0
- package/dist/svelte/__tests__/UsageLearning.test.js +140 -0
- package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte +21 -4
- package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts +5 -1
- package/dist/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.d.ts.map +1 -1
- 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/components/FieldPolicyControlPanel.svelte +28 -1
- package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts +3 -0
- package/dist/svelte/components/FieldPolicyControlPanel.svelte.d.ts.map +1 -1
- package/dist/svelte/components/FieldPolicyGearButton.svelte +8 -1
- package/dist/svelte/components/FieldPolicyGearButton.svelte.d.ts.map +1 -1
- package/dist/svelte/components/FieldPolicyGearProvider.svelte +34 -0
- package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts +3 -0
- package/dist/svelte/components/FieldPolicyGearProvider.svelte.d.ts.map +1 -1
- 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/ObjectForm.svelte +91 -2
- package/dist/svelte/components/ObjectForm.svelte.d.ts +11 -1
- package/dist/svelte/components/ObjectForm.svelte.d.ts.map +1 -1
- package/dist/svelte/gear-context.svelte.d.ts +2 -0
- package/dist/svelte/gear-context.svelte.d.ts.map +1 -1
- package/dist/svelte/index.d.ts +6 -1
- package/dist/svelte/index.d.ts.map +1 -1
- package/dist/svelte/index.js +4 -1
- 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/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 +40 -0
- package/dist/types.d.ts.map +1 -1
- 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 +8 -8
|
@@ -254,6 +254,137 @@ describe('ObjectForm component', () => {
|
|
|
254
254
|
await userEvent.click(submit);
|
|
255
255
|
expect(onsubmit).toHaveBeenCalledTimes(1);
|
|
256
256
|
});
|
|
257
|
+
it('reports only after a synchronous host persistence acknowledgement', async () => {
|
|
258
|
+
const onsubmit = vi.fn(() => true);
|
|
259
|
+
const reportUsage = vi.fn(() => {
|
|
260
|
+
throw new Error('metrics unavailable');
|
|
261
|
+
});
|
|
262
|
+
render(ObjectFormActionsFixture, {
|
|
263
|
+
props: { fields, policy, onsubmit, usageReporter: { reportUsage } },
|
|
264
|
+
});
|
|
265
|
+
await userEvent.type(screen.getByRole('textbox', { name: 'Name' }), 'Deluxe');
|
|
266
|
+
await userEvent.click(screen.getByRole('button', { name: 'Save product' }));
|
|
267
|
+
expect(onsubmit).toHaveBeenCalledTimes(1);
|
|
268
|
+
expect(reportUsage).toHaveBeenCalledWith({
|
|
269
|
+
entries: [{ objectRef: '@test:Product', fieldName: 'name' }],
|
|
270
|
+
});
|
|
271
|
+
const metadata = screen.getByRole('textbox', {
|
|
272
|
+
name: 'Metadata',
|
|
273
|
+
});
|
|
274
|
+
metadata.value = '{not json}';
|
|
275
|
+
await fireEvent.input(metadata);
|
|
276
|
+
await userEvent.click(screen.getByRole('button', { name: 'Save product' }));
|
|
277
|
+
expect(reportUsage).toHaveBeenCalledTimes(1);
|
|
278
|
+
});
|
|
279
|
+
it('reports after an asynchronous host persistence acknowledgement', async () => {
|
|
280
|
+
const onsubmit = vi.fn(async () => true);
|
|
281
|
+
const reportUsage = vi.fn();
|
|
282
|
+
render(ObjectFormActionsFixture, {
|
|
283
|
+
props: { fields, policy, onsubmit, usageReporter: { reportUsage } },
|
|
284
|
+
});
|
|
285
|
+
await userEvent.type(screen.getByRole('textbox', { name: 'Name' }), 'Deluxe');
|
|
286
|
+
await userEvent.click(screen.getByRole('button', { name: 'Save product' }));
|
|
287
|
+
await vi.waitFor(() => expect(reportUsage).toHaveBeenCalledTimes(1));
|
|
288
|
+
});
|
|
289
|
+
it('reports the submitted values when a successful create clears its bound record', async () => {
|
|
290
|
+
const reportUsage = vi.fn();
|
|
291
|
+
render(ObjectFormActionsFixture, {
|
|
292
|
+
props: {
|
|
293
|
+
fields,
|
|
294
|
+
policy,
|
|
295
|
+
onsubmit: async () => true,
|
|
296
|
+
usageReporter: { reportUsage },
|
|
297
|
+
resetAfterSuccessfulSubmit: true,
|
|
298
|
+
},
|
|
299
|
+
});
|
|
300
|
+
await userEvent.type(screen.getByRole('textbox', { name: 'Name' }), 'Deluxe');
|
|
301
|
+
await userEvent.click(screen.getByRole('button', { name: 'Save product' }));
|
|
302
|
+
await vi.waitFor(() => expect(reportUsage).toHaveBeenCalledWith({
|
|
303
|
+
entries: [{ objectRef: '@test:Product', fieldName: 'name' }],
|
|
304
|
+
}));
|
|
305
|
+
});
|
|
306
|
+
it('keeps named void and Promise<void> persistence handlers compatible without treating either as success', async () => {
|
|
307
|
+
function legacyVoidHandler(_event) { }
|
|
308
|
+
async function legacyAsyncVoidHandler(_event) { }
|
|
309
|
+
const handlers = [
|
|
310
|
+
legacyVoidHandler,
|
|
311
|
+
legacyAsyncVoidHandler,
|
|
312
|
+
];
|
|
313
|
+
for (const onsubmit of handlers) {
|
|
314
|
+
const reportUsage = vi.fn();
|
|
315
|
+
const view = render(ObjectFormActionsFixture, {
|
|
316
|
+
props: { fields, policy, onsubmit, usageReporter: { reportUsage } },
|
|
317
|
+
});
|
|
318
|
+
await userEvent.type(screen.getByRole('textbox', { name: 'Name' }), 'Deluxe');
|
|
319
|
+
await userEvent.click(screen.getByRole('button', { name: 'Save product' }));
|
|
320
|
+
await Promise.resolve();
|
|
321
|
+
expect(reportUsage).not.toHaveBeenCalled();
|
|
322
|
+
view.unmount();
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
it('marks a count-only text default as matched after persistence', async () => {
|
|
326
|
+
const policyWithTextDefault = {
|
|
327
|
+
...policy,
|
|
328
|
+
fields: {
|
|
329
|
+
...policy.fields,
|
|
330
|
+
name: {
|
|
331
|
+
...policy.fields.name,
|
|
332
|
+
hasDefault: true,
|
|
333
|
+
defaultValue: 'Default product name',
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
const reportUsage = vi.fn();
|
|
338
|
+
render(ObjectFormActionsFixture, {
|
|
339
|
+
props: {
|
|
340
|
+
fields,
|
|
341
|
+
policy: policyWithTextDefault,
|
|
342
|
+
onsubmit: () => true,
|
|
343
|
+
usageReporter: { reportUsage },
|
|
344
|
+
},
|
|
345
|
+
});
|
|
346
|
+
await tick();
|
|
347
|
+
await userEvent.click(screen.getByRole('button', { name: 'Save product' }));
|
|
348
|
+
expect(reportUsage).toHaveBeenCalledWith({
|
|
349
|
+
entries: [
|
|
350
|
+
{
|
|
351
|
+
objectRef: '@test:Product',
|
|
352
|
+
fieldName: 'name',
|
|
353
|
+
matchedDefault: true,
|
|
354
|
+
},
|
|
355
|
+
],
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
it('does not report when the host cancels, omits success, rejects, or local validation fails', async () => {
|
|
359
|
+
let attempt = 0;
|
|
360
|
+
const onsubmit = vi.fn(async () => {
|
|
361
|
+
attempt++;
|
|
362
|
+
if (attempt === 1)
|
|
363
|
+
return undefined;
|
|
364
|
+
if (attempt === 2)
|
|
365
|
+
return false;
|
|
366
|
+
throw new Error('persistence failed');
|
|
367
|
+
});
|
|
368
|
+
const reportUsage = vi.fn();
|
|
369
|
+
render(ObjectFormActionsFixture, {
|
|
370
|
+
props: { fields, policy, onsubmit, usageReporter: { reportUsage } },
|
|
371
|
+
});
|
|
372
|
+
await userEvent.type(screen.getByRole('textbox', { name: 'Name' }), 'Deluxe');
|
|
373
|
+
const submit = screen.getByRole('button', { name: 'Save product' });
|
|
374
|
+
await userEvent.click(submit);
|
|
375
|
+
await userEvent.click(submit);
|
|
376
|
+
await userEvent.click(submit);
|
|
377
|
+
await vi.waitFor(() => expect(onsubmit).toHaveBeenCalledTimes(3));
|
|
378
|
+
expect(reportUsage).not.toHaveBeenCalled();
|
|
379
|
+
const metadata = screen.getByRole('textbox', {
|
|
380
|
+
name: 'Metadata',
|
|
381
|
+
});
|
|
382
|
+
metadata.value = '{not json}';
|
|
383
|
+
await fireEvent.input(metadata);
|
|
384
|
+
await userEvent.click(submit);
|
|
385
|
+
expect(onsubmit).toHaveBeenCalledTimes(3);
|
|
386
|
+
expect(reportUsage).not.toHaveBeenCalled();
|
|
387
|
+
});
|
|
257
388
|
it('is axe-clean for its generated basic form', async () => {
|
|
258
389
|
const { container } = render(ObjectFormFixture, {
|
|
259
390
|
props: { fields, policy },
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { expectNoA11yViolations, render, screen, userEvent, } from '@happyvertical/smrt-vitest/svelte';
|
|
3
|
+
import { describe, expect, it, vi } from 'vitest';
|
|
4
|
+
import FieldPolicySuggestionQueue from '../components/FieldPolicySuggestionQueue.svelte';
|
|
5
|
+
import { parsePendingFieldPolicySuggestions, } from '../suggestions.js';
|
|
6
|
+
import { collectFieldUsageEntries, reportFieldUsage, } from '../usage-capture.js';
|
|
7
|
+
import SuggestionGearFixture from './fixtures/SuggestionGearFixture.svelte';
|
|
8
|
+
const pending = {
|
|
9
|
+
suggestions: [
|
|
10
|
+
{
|
|
11
|
+
id: 'suggestion-1',
|
|
12
|
+
objectRef: '@test:Widget',
|
|
13
|
+
fieldName: 'status',
|
|
14
|
+
kind: 'promote',
|
|
15
|
+
proposedValue: null,
|
|
16
|
+
evidence: { summary: '6 users set this field 12 times.' },
|
|
17
|
+
status: 'pending',
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
total: 1,
|
|
21
|
+
};
|
|
22
|
+
function suggestionAdapter() {
|
|
23
|
+
return {
|
|
24
|
+
pendingSuggestions: vi.fn(async () => pending),
|
|
25
|
+
acceptSuggestion: vi.fn(async () => undefined),
|
|
26
|
+
dismissSuggestion: vi.fn(async () => undefined),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const editorAdapter = {
|
|
30
|
+
load: async () => ({
|
|
31
|
+
capabilities: { manage: true, personalize: false },
|
|
32
|
+
personalLowerDefaultUsable: {},
|
|
33
|
+
policy: { objectRef: '@test:Widget', fields: {}, layers: {} },
|
|
34
|
+
rows: { app: [], tenant: [], user: [] },
|
|
35
|
+
}),
|
|
36
|
+
create: async () => undefined,
|
|
37
|
+
update: async () => undefined,
|
|
38
|
+
delete: async () => undefined,
|
|
39
|
+
};
|
|
40
|
+
describe('field usage capture', () => {
|
|
41
|
+
it('keeps free-form values out of browser telemetry while retaining count signals', () => {
|
|
42
|
+
expect(collectFieldUsageEntries({
|
|
43
|
+
objectRef: '@test:Widget',
|
|
44
|
+
fields: {
|
|
45
|
+
title: 'text',
|
|
46
|
+
enabled: 'boolean',
|
|
47
|
+
count: 'integer',
|
|
48
|
+
ownerId: 'foreignKey',
|
|
49
|
+
metadata: 'json',
|
|
50
|
+
},
|
|
51
|
+
values: {
|
|
52
|
+
title: 'A title',
|
|
53
|
+
enabled: false,
|
|
54
|
+
count: 0,
|
|
55
|
+
ownerId: '4f552b7e-88a4-499a-9ce4-6a88bec3b439',
|
|
56
|
+
metadata: { email: 'member@example.test' },
|
|
57
|
+
omitted: 'not rendered',
|
|
58
|
+
},
|
|
59
|
+
defaults: {
|
|
60
|
+
title: { hasDefault: true, defaultValue: 'A title' },
|
|
61
|
+
count: { hasDefault: true, defaultValue: 1 },
|
|
62
|
+
metadata: {
|
|
63
|
+
hasDefault: true,
|
|
64
|
+
defaultValue: { email: 'member@example.test' },
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
})).toEqual([
|
|
68
|
+
{
|
|
69
|
+
objectRef: '@test:Widget',
|
|
70
|
+
fieldName: 'title',
|
|
71
|
+
matchedDefault: true,
|
|
72
|
+
},
|
|
73
|
+
{ objectRef: '@test:Widget', fieldName: 'enabled', value: false },
|
|
74
|
+
{ objectRef: '@test:Widget', fieldName: 'count' },
|
|
75
|
+
{
|
|
76
|
+
objectRef: '@test:Widget',
|
|
77
|
+
fieldName: 'ownerId',
|
|
78
|
+
value: '4f552b7e-88a4-499a-9ce4-6a88bec3b439',
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
objectRef: '@test:Widget',
|
|
82
|
+
fieldName: 'metadata',
|
|
83
|
+
matchedDefault: true,
|
|
84
|
+
},
|
|
85
|
+
]);
|
|
86
|
+
});
|
|
87
|
+
it('contains synchronous and asynchronous reporter failures outside the submit path', async () => {
|
|
88
|
+
const sync = {
|
|
89
|
+
reportUsage: () => {
|
|
90
|
+
throw new Error('offline');
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
const rejected = {
|
|
94
|
+
reportUsage: async () => {
|
|
95
|
+
throw new Error('offline');
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
expect(() => reportFieldUsage(sync, [
|
|
99
|
+
{ objectRef: '@test:Widget', fieldName: 'title' },
|
|
100
|
+
])).not.toThrow();
|
|
101
|
+
expect(() => reportFieldUsage(rejected, [
|
|
102
|
+
{ objectRef: '@test:Widget', fieldName: 'title' },
|
|
103
|
+
])).not.toThrow();
|
|
104
|
+
await Promise.resolve();
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
describe('field policy suggestion review', () => {
|
|
108
|
+
it('fails closed for malformed generated-action output', () => {
|
|
109
|
+
expect(() => parsePendingFieldPolicySuggestions({ suggestions: [], total: '1' })).toThrow(/Unable to load pending/i);
|
|
110
|
+
expect(() => parsePendingFieldPolicySuggestions({
|
|
111
|
+
suggestions: [{ id: 'missing fields' }],
|
|
112
|
+
total: 1,
|
|
113
|
+
})).toThrow(/Unable to load pending/i);
|
|
114
|
+
});
|
|
115
|
+
it('renders an accessible reviewed queue and refreshes after approve or dismiss', async () => {
|
|
116
|
+
const adapter = suggestionAdapter();
|
|
117
|
+
const { container } = render(FieldPolicySuggestionQueue, {
|
|
118
|
+
props: { adapter, objectRefs: ['@test:Widget'] },
|
|
119
|
+
});
|
|
120
|
+
await vi.waitFor(() => expect(screen.getByText(/6 users set/i)).toBeVisible());
|
|
121
|
+
expect(screen.getByRole('heading', { name: 'Pending field suggestions' })).toBeVisible();
|
|
122
|
+
await userEvent.click(screen.getByRole('button', { name: 'Approve' }));
|
|
123
|
+
await vi.waitFor(() => expect(adapter.acceptSuggestion).toHaveBeenCalledWith({
|
|
124
|
+
id: 'suggestion-1',
|
|
125
|
+
}));
|
|
126
|
+
expect(adapter.pendingSuggestions).toHaveBeenCalledWith({
|
|
127
|
+
objectRefs: ['@test:Widget'],
|
|
128
|
+
});
|
|
129
|
+
await expectNoA11yViolations(container);
|
|
130
|
+
});
|
|
131
|
+
it('announces a pending-suggestion count on the policy gear without exposing suggestion details', async () => {
|
|
132
|
+
render(SuggestionGearFixture, {
|
|
133
|
+
props: { adapter: editorAdapter, suggestionAdapter: suggestionAdapter() },
|
|
134
|
+
});
|
|
135
|
+
await vi.waitFor(() => expect(screen.getByRole('button', {
|
|
136
|
+
name: 'Field settings, 1 pending suggestion',
|
|
137
|
+
})).toBeVisible());
|
|
138
|
+
expect(screen.getByText('1')).toHaveAttribute('aria-hidden', 'true');
|
|
139
|
+
});
|
|
140
|
+
});
|
|
@@ -1,19 +1,36 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { ResolvedObjectFieldPolicy } from '../../../types.js';
|
|
3
|
-
import ObjectForm
|
|
3
|
+
import ObjectForm, {
|
|
4
|
+
type ObjectFormProps,
|
|
5
|
+
} from '../../components/ObjectForm.svelte';
|
|
4
6
|
import type { ObjectFormFieldDefinition } from '../../types.js';
|
|
7
|
+
import type { FieldUsageReporter } from '../../usage-capture.js';
|
|
5
8
|
|
|
6
9
|
interface Props {
|
|
7
10
|
fields: Record<string, ObjectFormFieldDefinition>;
|
|
8
11
|
policy: ResolvedObjectFieldPolicy;
|
|
9
|
-
onsubmit:
|
|
12
|
+
onsubmit: NonNullable<ObjectFormProps['onsubmit']>;
|
|
13
|
+
usageReporter?: FieldUsageReporter;
|
|
14
|
+
resetAfterSuccessfulSubmit?: boolean;
|
|
10
15
|
}
|
|
11
16
|
|
|
12
|
-
let {
|
|
17
|
+
let {
|
|
18
|
+
fields,
|
|
19
|
+
policy,
|
|
20
|
+
onsubmit,
|
|
21
|
+
usageReporter,
|
|
22
|
+
resetAfterSuccessfulSubmit = false,
|
|
23
|
+
}: Props = $props();
|
|
13
24
|
let record = $state<Record<string, unknown>>({});
|
|
25
|
+
|
|
26
|
+
async function submit(event: SubmitEvent): Promise<boolean | undefined> {
|
|
27
|
+
const result = await onsubmit(event);
|
|
28
|
+
if (result === true && resetAfterSuccessfulSubmit) record = {};
|
|
29
|
+
return result === true ? true : undefined;
|
|
30
|
+
}
|
|
14
31
|
</script>
|
|
15
32
|
|
|
16
|
-
<ObjectForm objectRef={policy.objectRef} {fields} {policy} bind:value={record} {
|
|
33
|
+
<ObjectForm objectRef={policy.objectRef} {fields} {policy} bind:value={record} onsubmit={submit} {usageReporter}>
|
|
17
34
|
{#snippet actions()}
|
|
18
35
|
<button type="submit">Save product</button>
|
|
19
36
|
{/snippet}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import type { ResolvedObjectFieldPolicy } from '../../../types.js';
|
|
2
|
+
import { type ObjectFormProps } from '../../components/ObjectForm.svelte';
|
|
2
3
|
import type { ObjectFormFieldDefinition } from '../../types.js';
|
|
4
|
+
import type { FieldUsageReporter } from '../../usage-capture.js';
|
|
3
5
|
interface Props {
|
|
4
6
|
fields: Record<string, ObjectFormFieldDefinition>;
|
|
5
7
|
policy: ResolvedObjectFieldPolicy;
|
|
6
|
-
onsubmit:
|
|
8
|
+
onsubmit: NonNullable<ObjectFormProps['onsubmit']>;
|
|
9
|
+
usageReporter?: FieldUsageReporter;
|
|
10
|
+
resetAfterSuccessfulSubmit?: boolean;
|
|
7
11
|
}
|
|
8
12
|
declare const ObjectFormActionsFixture: import("svelte").Component<Props, {}, "">;
|
|
9
13
|
type ObjectFormActionsFixture = ReturnType<typeof ObjectFormActionsFixture>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ObjectFormActionsFixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"ObjectFormActionsFixture.svelte.d.ts","sourceRoot":"","sources":["../../../../src/svelte/__tests__/fixtures/ObjectFormActionsFixture.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AACnE,OAAmB,EACjB,KAAK,eAAe,EACrB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,UAAU,KAAK;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IAClD,MAAM,EAAE,yBAAyB,CAAC;IAClC,QAAQ,EAAE,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;IACnD,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,0BAA0B,CAAC,EAAE,OAAO,CAAC;CACtC;AAgCD,QAAA,MAAM,wBAAwB,2CAAwC,CAAC;AACvE,KAAK,wBAAwB,GAAG,UAAU,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAC5E,eAAe,wBAAwB,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"}
|
|
@@ -29,7 +29,9 @@ import {
|
|
|
29
29
|
orgRowIdsForObject,
|
|
30
30
|
prunableDriftRows,
|
|
31
31
|
} from '../settings-catalog.js';
|
|
32
|
+
import type { FieldPolicySuggestionAdapter } from '../suggestions.js';
|
|
32
33
|
import FieldPolicyEditor from './FieldPolicyEditor.svelte';
|
|
34
|
+
import FieldPolicySuggestionQueue from './FieldPolicySuggestionQueue.svelte';
|
|
33
35
|
|
|
34
36
|
export interface FieldPolicyCatalogComponentProps {
|
|
35
37
|
page: FieldPolicySettingsCatalogPage;
|
|
@@ -48,6 +50,8 @@ export interface FieldPolicyControlPanelProps {
|
|
|
48
50
|
heading?: string;
|
|
49
51
|
onchanged?: () => void;
|
|
50
52
|
confirmAction?: (message: string) => boolean | Promise<boolean>;
|
|
53
|
+
/** Optional reviewed-suggestion queue transport. */
|
|
54
|
+
suggestionAdapter?: FieldPolicySuggestionAdapter;
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
let {
|
|
@@ -59,6 +63,7 @@ let {
|
|
|
59
63
|
heading = 'Field settings',
|
|
60
64
|
onchanged,
|
|
61
65
|
confirmAction,
|
|
66
|
+
suggestionAdapter,
|
|
62
67
|
}: FieldPolicyControlPanelProps = $props();
|
|
63
68
|
|
|
64
69
|
// Before client effects run (including SSR), render the server snapshot.
|
|
@@ -70,6 +75,7 @@ let loadingEditor = $state(false);
|
|
|
70
75
|
let busy = $state(false);
|
|
71
76
|
let error = $state<string | null>(null);
|
|
72
77
|
let generation = 0;
|
|
78
|
+
let auditGeneration = 0;
|
|
73
79
|
|
|
74
80
|
const Catalog = $derived(catalog);
|
|
75
81
|
const visibleAudit = $derived(audit ?? data.audit);
|
|
@@ -83,6 +89,9 @@ const preservedParams = $derived(fieldPolicyCatalogPreservedParams(data));
|
|
|
83
89
|
|
|
84
90
|
$effect(() => {
|
|
85
91
|
data;
|
|
92
|
+
// A prop snapshot supersedes every in-flight mutation refresh. Without this
|
|
93
|
+
// invalidation, an older response can overwrite newer SSR/navigation data.
|
|
94
|
+
auditGeneration++;
|
|
86
95
|
audit = data.audit;
|
|
87
96
|
editorState = null;
|
|
88
97
|
editorOpen = false;
|
|
@@ -114,11 +123,15 @@ async function loadEditor(): Promise<void> {
|
|
|
114
123
|
}
|
|
115
124
|
|
|
116
125
|
async function refreshAudit(): Promise<boolean> {
|
|
126
|
+
const token = ++auditGeneration;
|
|
117
127
|
const refs = auditObjectRefs(data.page);
|
|
118
128
|
try {
|
|
119
|
-
|
|
129
|
+
const refreshed = await adapter.loadAudit({ ...refs, includeDrift: true });
|
|
130
|
+
if (token !== auditGeneration) return false;
|
|
131
|
+
audit = refreshed;
|
|
120
132
|
return true;
|
|
121
133
|
} catch (cause) {
|
|
134
|
+
if (token !== auditGeneration) return false;
|
|
122
135
|
error =
|
|
123
136
|
cause instanceof Error
|
|
124
137
|
? cause.message
|
|
@@ -195,6 +208,13 @@ function valueText(cell: FieldPolicyLayerCell): string {
|
|
|
195
208
|
return String(cell.defaultValue);
|
|
196
209
|
}
|
|
197
210
|
}
|
|
211
|
+
|
|
212
|
+
async function suggestionChanged(): Promise<void> {
|
|
213
|
+
if (await refreshAudit()) {
|
|
214
|
+
await loadEditor();
|
|
215
|
+
onchanged?.();
|
|
216
|
+
}
|
|
217
|
+
}
|
|
198
218
|
</script>
|
|
199
219
|
|
|
200
220
|
{#if canManage}
|
|
@@ -234,6 +254,13 @@ function valueText(cell: FieldPolicyLayerCell): string {
|
|
|
234
254
|
onmutated={editorMutated}
|
|
235
255
|
/>
|
|
236
256
|
{/if}
|
|
257
|
+
{#if suggestionAdapter}
|
|
258
|
+
<FieldPolicySuggestionQueue
|
|
259
|
+
adapter={suggestionAdapter}
|
|
260
|
+
objectRefs={auditObjectRefs(data.page).objectRefs}
|
|
261
|
+
onchanged={suggestionChanged}
|
|
262
|
+
/>
|
|
263
|
+
{/if}
|
|
237
264
|
{#if prunableDriftRows(visibleAudit).length}
|
|
238
265
|
<section class="field-policy-control-panel__drift" aria-label="Manifest drift">
|
|
239
266
|
<h2>Manifest drift</h2>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Component, Snippet } from 'svelte';
|
|
2
2
|
import type { FieldPolicyDetailItem, FieldPolicySettingsCatalogData, FieldPolicySettingsCatalogPage } from '../../settings-catalog.js';
|
|
3
3
|
import { type FieldPolicyControlPanelAdapter } from '../settings-catalog.js';
|
|
4
|
+
import type { FieldPolicySuggestionAdapter } from '../suggestions.js';
|
|
4
5
|
export interface FieldPolicyCatalogComponentProps {
|
|
5
6
|
page: FieldPolicySettingsCatalogPage;
|
|
6
7
|
baseUrl: string;
|
|
@@ -19,6 +20,8 @@ export interface FieldPolicyControlPanelProps {
|
|
|
19
20
|
heading?: string;
|
|
20
21
|
onchanged?: () => void;
|
|
21
22
|
confirmAction?: (message: string) => boolean | Promise<boolean>;
|
|
23
|
+
/** Optional reviewed-suggestion queue transport. */
|
|
24
|
+
suggestionAdapter?: FieldPolicySuggestionAdapter;
|
|
22
25
|
}
|
|
23
26
|
declare const FieldPolicyControlPanel: Component<FieldPolicyControlPanelProps, {}, "">;
|
|
24
27
|
type FieldPolicyControlPanel = ReturnType<typeof FieldPolicyControlPanel>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldPolicyControlPanel.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FieldPolicyControlPanel.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EACV,qBAAqB,EACrB,8BAA8B,EAC9B,8BAA8B,EAC/B,MAAM,2BAA2B,CAAC;AASnC,OAAO,EAGL,KAAK,8BAA8B,EAMpC,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"FieldPolicyControlPanel.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FieldPolicyControlPanel.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EACV,qBAAqB,EACrB,8BAA8B,EAC9B,8BAA8B,EAC/B,MAAM,2BAA2B,CAAC;AASnC,OAAO,EAGL,KAAK,8BAA8B,EAMpC,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AAKtE,MAAM,WAAW,gCAAgC;IAC/C,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;IACzC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,8BAA8B,CAAC;IACrC,OAAO,EAAE,8BAA8B,CAAC;IACxC,OAAO,EAAE,SAAS,CAAC,gCAAgC,CAAC,CAAC;IACrD,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAChE,oDAAoD;IACpD,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;CAClD;AAsOD,QAAA,MAAM,uBAAuB,iDAAwC,CAAC;AACtE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC1E,eAAe,uBAAuB,CAAC"}
|
|
@@ -10,8 +10,15 @@ const gear = getFieldPolicyGearContext();
|
|
|
10
10
|
</script>
|
|
11
11
|
|
|
12
12
|
{#if gear.canEdit}
|
|
13
|
-
<Button type="button" variant="ghost" class={className} aria-haspopup="dialog" onclick={() => gear.show()}>
|
|
13
|
+
<Button type="button" variant="ghost" class={className} aria-haspopup="dialog" aria-label={gear.pendingSuggestionCount > 0 ? `${label}, ${gear.pendingSuggestionCount} pending suggestion${gear.pendingSuggestionCount === 1 ? '' : 's'}` : label} onclick={() => gear.show()}>
|
|
14
14
|
<span aria-hidden="true">⚙</span>
|
|
15
15
|
<span>{label}</span>
|
|
16
|
+
{#if gear.pendingSuggestionCount > 0}
|
|
17
|
+
<span class="field-policy-gear-button__badge" aria-hidden="true">{gear.pendingSuggestionCount}</span>
|
|
18
|
+
{/if}
|
|
16
19
|
</Button>
|
|
17
20
|
{/if}
|
|
21
|
+
|
|
22
|
+
<style>
|
|
23
|
+
.field-policy-gear-button__badge { border-radius: 999px; background: var(--smrt-color-secondary-container, #e8def8); min-inline-size: 1.25rem; padding-inline: 0.25rem; text-align: center; }
|
|
24
|
+
</style>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldPolicyGearButton.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FieldPolicyGearButton.svelte.ts"],"names":[],"mappings":"AAMC,KAAK,gBAAgB,GAAI;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"FieldPolicyGearButton.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FieldPolicyGearButton.svelte.ts"],"names":[],"mappings":"AAMC,KAAK,gBAAgB,GAAI;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AA0B7D,QAAA,MAAM,qBAAqB,sDAAwC,CAAC;AACpE,KAAK,qBAAqB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAC;AACtE,eAAe,qBAAqB,CAAC"}
|
|
@@ -12,6 +12,10 @@ import {
|
|
|
12
12
|
setFieldPolicyGearContext,
|
|
13
13
|
} from '../gear-context.svelte.js';
|
|
14
14
|
import type { FieldInputRegistry } from '../input-registry.js';
|
|
15
|
+
import {
|
|
16
|
+
type FieldPolicySuggestionAdapter,
|
|
17
|
+
parsePendingFieldPolicySuggestions,
|
|
18
|
+
} from '../suggestions.js';
|
|
15
19
|
import type { ObjectFormFieldDefinition } from '../types.js';
|
|
16
20
|
import FieldPolicyEditor from './FieldPolicyEditor.svelte';
|
|
17
21
|
|
|
@@ -22,6 +26,8 @@ interface Props {
|
|
|
22
26
|
inputRegistry?: FieldInputRegistry;
|
|
23
27
|
/** Hosts in an app-wide context pass app; tenant hosts retain the default. */
|
|
24
28
|
organizationScope?: FieldPolicyOrganizationScope;
|
|
29
|
+
/** Optional reviewed-suggestion transport for the gear badge. */
|
|
30
|
+
suggestionAdapter?: FieldPolicySuggestionAdapter;
|
|
25
31
|
children?: Snippet;
|
|
26
32
|
}
|
|
27
33
|
|
|
@@ -31,6 +37,7 @@ let {
|
|
|
31
37
|
adapter,
|
|
32
38
|
inputRegistry,
|
|
33
39
|
organizationScope = 'tenant',
|
|
40
|
+
suggestionAdapter,
|
|
34
41
|
children,
|
|
35
42
|
}: Props = $props();
|
|
36
43
|
|
|
@@ -38,6 +45,7 @@ let editorState = $state<FieldPolicyEditorState | null>(null);
|
|
|
38
45
|
let error = $state<string | null>(null);
|
|
39
46
|
let open = $state(false);
|
|
40
47
|
let loading = $state(false);
|
|
48
|
+
let pendingSuggestionCount = $state(0);
|
|
41
49
|
|
|
42
50
|
const controller: FieldPolicyGearController = {
|
|
43
51
|
get state() {
|
|
@@ -55,6 +63,9 @@ const controller: FieldPolicyGearController = {
|
|
|
55
63
|
(editorState.capabilities.manage || editorState.capabilities.personalize)
|
|
56
64
|
);
|
|
57
65
|
},
|
|
66
|
+
get pendingSuggestionCount() {
|
|
67
|
+
return pendingSuggestionCount;
|
|
68
|
+
},
|
|
58
69
|
show() {
|
|
59
70
|
if (this.canEdit) open = true;
|
|
60
71
|
},
|
|
@@ -104,16 +115,39 @@ async function reload(generation = ++loadGeneration): Promise<void> {
|
|
|
104
115
|
}
|
|
105
116
|
}
|
|
106
117
|
|
|
118
|
+
async function reloadPendingSuggestions(
|
|
119
|
+
generation = ++suggestionGeneration,
|
|
120
|
+
): Promise<void> {
|
|
121
|
+
if (!suggestionAdapter) {
|
|
122
|
+
pendingSuggestionCount = 0;
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const result = parsePendingFieldPolicySuggestions(
|
|
127
|
+
await suggestionAdapter.pendingSuggestions({ objectRefs: [objectRef] }),
|
|
128
|
+
);
|
|
129
|
+
if (generation === suggestionGeneration) {
|
|
130
|
+
pendingSuggestionCount = result.total;
|
|
131
|
+
}
|
|
132
|
+
} catch {
|
|
133
|
+
// A metrics/read failure must not suppress ordinary policy editing.
|
|
134
|
+
if (generation === suggestionGeneration) pendingSuggestionCount = 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
107
138
|
let loadGeneration = 0;
|
|
139
|
+
let suggestionGeneration = 0;
|
|
108
140
|
$effect(() => {
|
|
109
141
|
const generation = ++loadGeneration;
|
|
110
142
|
editorState = null;
|
|
111
143
|
error = null;
|
|
112
144
|
open = false;
|
|
113
145
|
void reload(generation);
|
|
146
|
+
void reloadPendingSuggestions();
|
|
114
147
|
return () => {
|
|
115
148
|
// A delayed transport response must never repopulate a prior object.
|
|
116
149
|
if (loadGeneration === generation) loadGeneration++;
|
|
150
|
+
suggestionGeneration++;
|
|
117
151
|
};
|
|
118
152
|
});
|
|
119
153
|
</script>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Snippet } from 'svelte';
|
|
2
2
|
import { type FieldPolicyEditorAdapter, type FieldPolicyOrganizationScope } from '../field-policy-editor.js';
|
|
3
3
|
import type { FieldInputRegistry } from '../input-registry.js';
|
|
4
|
+
import { type FieldPolicySuggestionAdapter } from '../suggestions.js';
|
|
4
5
|
import type { ObjectFormFieldDefinition } from '../types.js';
|
|
5
6
|
interface Props {
|
|
6
7
|
objectRef: string;
|
|
@@ -9,6 +10,8 @@ interface Props {
|
|
|
9
10
|
inputRegistry?: FieldInputRegistry;
|
|
10
11
|
/** Hosts in an app-wide context pass app; tenant hosts retain the default. */
|
|
11
12
|
organizationScope?: FieldPolicyOrganizationScope;
|
|
13
|
+
/** Optional reviewed-suggestion transport for the gear badge. */
|
|
14
|
+
suggestionAdapter?: FieldPolicySuggestionAdapter;
|
|
12
15
|
children?: Snippet;
|
|
13
16
|
}
|
|
14
17
|
declare const FieldPolicyGearProvider: import("svelte").Component<Props, {}, "">;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FieldPolicyGearProvider.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FieldPolicyGearProvider.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,4BAA4B,EAElC,MAAM,2BAA2B,CAAC;AAKnC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAI7D,UAAU,KAAK;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAC5D,OAAO,EAAE,wBAAwB,CAAC;IAClC,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;
|
|
1
|
+
{"version":3,"file":"FieldPolicyGearProvider.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FieldPolicyGearProvider.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAEtC,OAAO,EAEL,KAAK,wBAAwB,EAC7B,KAAK,4BAA4B,EAElC,MAAM,2BAA2B,CAAC;AAKnC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,EACL,KAAK,4BAA4B,EAElC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAI7D,UAAU,KAAK;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAC5D,OAAO,EAAE,wBAAwB,CAAC;IAClC,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;IACjD,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,4BAA4B,CAAC;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAoJD,QAAA,MAAM,uBAAuB,2CAAwC,CAAC;AACtE,KAAK,uBAAuB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAC1E,eAAe,uBAAuB,CAAC"}
|