attaform 0.17.2 → 0.18.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 +77 -36
- package/dist/chunks/devtools.cjs +10 -37
- package/dist/chunks/devtools.cjs.map +1 -1
- package/dist/chunks/devtools.mjs +10 -37
- package/dist/chunks/devtools.mjs.map +1 -1
- package/dist/chunks/indexeddb.cjs +4 -4
- package/dist/chunks/indexeddb.cjs.map +1 -1
- package/dist/chunks/indexeddb.mjs +1 -1
- package/dist/chunks/local-storage.cjs +2 -2
- package/dist/chunks/local-storage.cjs.map +1 -1
- package/dist/chunks/local-storage.mjs +1 -1
- package/dist/chunks/session-storage.cjs +2 -2
- package/dist/chunks/session-storage.cjs.map +1 -1
- package/dist/chunks/session-storage.mjs +1 -1
- package/dist/index.cjs +42 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +159 -196
- package/dist/index.d.mts +159 -196
- package/dist/index.d.ts +159 -196
- package/dist/index.mjs +5 -7
- package/dist/index.mjs.map +1 -1
- package/dist/nuxt.cjs +31 -40
- package/dist/nuxt.cjs.map +1 -1
- package/dist/nuxt.d.cts +8 -1
- package/dist/nuxt.d.mts +8 -1
- package/dist/nuxt.d.ts +8 -1
- package/dist/nuxt.mjs +32 -41
- package/dist/nuxt.mjs.map +1 -1
- package/dist/runtime/components/AttaformDevtoolsPanel.d.vue.ts +7 -0
- package/dist/runtime/components/AttaformDevtoolsPanel.vue +453 -0
- package/dist/runtime/components/AttaformDevtoolsPanel.vue.d.ts +7 -0
- package/dist/runtime/components/DevtoolsValueTree.d.vue.ts +37 -0
- package/dist/runtime/components/DevtoolsValueTree.vue +192 -0
- package/dist/runtime/components/DevtoolsValueTree.vue.d.ts +37 -0
- package/dist/runtime/plugins/attaform.cjs +17 -6
- package/dist/runtime/plugins/attaform.cjs.map +1 -1
- package/dist/runtime/plugins/attaform.mjs +15 -4
- package/dist/runtime/plugins/attaform.mjs.map +1 -1
- package/dist/shared/attaform.5UhpSVFI.cjs +63 -0
- package/dist/shared/attaform.5UhpSVFI.cjs.map +1 -0
- package/dist/shared/attaform.BDdFdjeX.mjs +57 -0
- package/dist/shared/attaform.BDdFdjeX.mjs.map +1 -0
- package/dist/shared/attaform.Bgu9l6OG.d.cts +1651 -0
- package/dist/shared/attaform.BmDBu4ql.d.ts +1651 -0
- package/dist/shared/{attaform.Dee2rU1P.cjs → attaform.BqK_L4gK.cjs} +310 -24
- package/dist/shared/attaform.BqK_L4gK.cjs.map +1 -0
- package/dist/shared/{attaform.C_5aB6EQ.d.ts → attaform.BsMdl-35.d.cts} +754 -146
- package/dist/shared/{attaform.C_5aB6EQ.d.mts → attaform.BsMdl-35.d.mts} +754 -146
- package/dist/shared/{attaform.C_5aB6EQ.d.cts → attaform.BsMdl-35.d.ts} +754 -146
- package/dist/shared/attaform.Bubm_slq.cjs.map +1 -1
- package/dist/shared/{attaform.C6lbmMUe.d.ts → attaform.C3x1hKJC.d.mts} +4 -4
- package/dist/shared/{attaform.CuE-bS1C.d.mts → attaform.CWs1Z3p7.d.ts} +57 -23
- package/dist/shared/attaform.CXpzmj38.mjs.map +1 -1
- package/dist/shared/{attaform.C5MH4lNh.d.mts → attaform.CjmJpfLH.d.ts} +4 -4
- package/dist/shared/{attaform.Drt6fivF.mjs → attaform.CtNUB9nf.mjs} +74 -76
- package/dist/shared/attaform.CtNUB9nf.mjs.map +1 -0
- package/dist/shared/{attaform.C0iFnTN0.d.ts → attaform.D-hDvb98.d.cts} +57 -23
- package/dist/shared/attaform.DAH3kvav.d.mts +1651 -0
- package/dist/shared/{attaform.BPRHR3Zs.cjs → attaform.DUHru0OF.cjs} +83 -85
- package/dist/shared/attaform.DUHru0OF.cjs.map +1 -0
- package/dist/shared/{attaform.BV40t5y2.cjs → attaform.Dlk1jMuv.cjs} +245 -108
- package/dist/shared/attaform.Dlk1jMuv.cjs.map +1 -0
- package/dist/shared/{attaform.B3ZaPIzS.mjs → attaform.DsC3rZHG.mjs} +1804 -219
- package/dist/shared/attaform.DsC3rZHG.mjs.map +1 -0
- package/dist/shared/{attaform.DtMN-MAm.d.cts → attaform.Dzi89x8N.d.cts} +4 -4
- package/dist/shared/{attaform.Cer8JO_P.cjs → attaform.II89Pcf4.cjs} +1860 -272
- package/dist/shared/attaform.II89Pcf4.cjs.map +1 -0
- package/dist/shared/{attaform.CIEQgJnM.mjs → attaform.Xhg0AYNa.mjs} +300 -26
- package/dist/shared/attaform.Xhg0AYNa.mjs.map +1 -0
- package/dist/shared/{attaform.CpERWz3u.mjs → attaform.Xt0A3QUd.mjs} +232 -95
- package/dist/shared/attaform.Xt0A3QUd.mjs.map +1 -0
- package/dist/shared/{attaform.CHorcsIU.d.cts → attaform.bH7WvNad.d.mts} +57 -23
- package/dist/vite.cjs +270 -2
- package/dist/vite.cjs.map +1 -1
- package/dist/vite.mjs +266 -2
- package/dist/vite.mjs.map +1 -1
- package/dist/zod-v3.cjs +11 -8
- package/dist/zod-v3.cjs.map +1 -1
- package/dist/zod-v3.d.cts +6 -6
- package/dist/zod-v3.d.mts +6 -6
- package/dist/zod-v3.d.ts +6 -6
- package/dist/zod-v3.mjs +3 -3
- package/dist/zod-v4.cjs +11 -8
- package/dist/zod-v4.cjs.map +1 -1
- package/dist/zod-v4.d.cts +5 -5
- package/dist/zod-v4.d.mts +5 -5
- package/dist/zod-v4.d.ts +5 -5
- package/dist/zod-v4.mjs +3 -3
- package/dist/zod.cjs +15 -16
- package/dist/zod.cjs.map +1 -1
- package/dist/zod.d.cts +127 -40
- package/dist/zod.d.mts +127 -40
- package/dist/zod.d.ts +127 -40
- package/dist/zod.mjs +7 -11
- package/dist/zod.mjs.map +1 -1
- package/package.json +19 -5
- package/dist/shared/attaform.B1jvxsOF.d.mts +0 -156
- package/dist/shared/attaform.B3ZaPIzS.mjs.map +0 -1
- package/dist/shared/attaform.BBM2muQ9.cjs +0 -101
- package/dist/shared/attaform.BBM2muQ9.cjs.map +0 -1
- package/dist/shared/attaform.BPRHR3Zs.cjs.map +0 -1
- package/dist/shared/attaform.BV40t5y2.cjs.map +0 -1
- package/dist/shared/attaform.C6qzEdIM.d.cts +0 -156
- package/dist/shared/attaform.C8LVFVVe.cjs +0 -32
- package/dist/shared/attaform.C8LVFVVe.cjs.map +0 -1
- package/dist/shared/attaform.CIEQgJnM.mjs.map +0 -1
- package/dist/shared/attaform.CTwNcpLE.d.ts +0 -156
- package/dist/shared/attaform.Cer8JO_P.cjs.map +0 -1
- package/dist/shared/attaform.CpERWz3u.mjs.map +0 -1
- package/dist/shared/attaform.Dee2rU1P.cjs.map +0 -1
- package/dist/shared/attaform.Drt6fivF.mjs.map +0 -1
- package/dist/shared/attaform.Vo-Kft0t.mjs +0 -29
- package/dist/shared/attaform.Vo-Kft0t.mjs.map +0 -1
- package/dist/shared/attaform.h1sq3BFu.mjs +0 -92
- package/dist/shared/attaform.h1sq3BFu.mjs.map +0 -1
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
import { G as GenericForm, F as FormKey, d as UseFormReturnType, R as RegisterValue } from './attaform.C_5aB6EQ.cjs';
|
|
2
|
-
import { Ref } from 'vue';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Access an existing form from a descendant component without passing
|
|
6
|
-
* it through props. Counterpart to `useForm` — `useForm` creates and
|
|
7
|
-
* provides; `injectForm` looks up via Vue's inject mechanism.
|
|
8
|
-
*
|
|
9
|
-
* Two ways to call it:
|
|
10
|
-
*
|
|
11
|
-
* ```ts
|
|
12
|
-
* // Reach the nearest ancestor's anonymous useForm() call.
|
|
13
|
-
* const form = injectForm<SignupShape>()
|
|
14
|
-
*
|
|
15
|
-
* // Reach a specific form by its key — works from anywhere in the app.
|
|
16
|
-
* const cart = injectForm<CartShape>('cart')
|
|
17
|
-
* ```
|
|
18
|
-
*
|
|
19
|
-
* Resolution rules (no-key form):
|
|
20
|
-
* - Closest ambient ancestor wins.
|
|
21
|
-
* - Only anonymous `useForm()` (no `key`) fills the ambient slot;
|
|
22
|
-
* keyed forms are reachable only via `injectForm(key)`.
|
|
23
|
-
* - Inherits the resolved ancestor's `formInstanceId`.
|
|
24
|
-
*
|
|
25
|
-
* Resolution rules (keyed form): registry lookup by string key,
|
|
26
|
-
* independent of component-tree position.
|
|
27
|
-
*
|
|
28
|
-
* Returns `null` when no matching form exists (no ambient ancestor, or
|
|
29
|
-
* the named key isn't registered). A dev-mode warning points at the
|
|
30
|
-
* call site to help diagnose typos. Always narrow before using:
|
|
31
|
-
*
|
|
32
|
-
* ```ts
|
|
33
|
-
* const form = injectForm<Shape>('signup')
|
|
34
|
-
* if (!form) return
|
|
35
|
-
* form.register('email')
|
|
36
|
-
* ```
|
|
37
|
-
*
|
|
38
|
-
* Pass the `Form` generic explicitly — Vue's provide/inject erases
|
|
39
|
-
* generics, so the library can't recover the shape automatically.
|
|
40
|
-
*
|
|
41
|
-
* The form is kept alive for this component's lifetime; once every
|
|
42
|
-
* consumer unmounts, the form is cleaned up automatically.
|
|
43
|
-
*/
|
|
44
|
-
declare function injectForm<Form extends GenericForm, GetValueFormType extends GenericForm = Form>(key?: FormKey): UseFormReturnType<Form, GetValueFormType> | null;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Re-bind a parent's `v-register` onto an inner native element. Use
|
|
48
|
-
* inside a component that wraps a single form field whose root is
|
|
49
|
-
* NOT the input itself (e.g. a labelled-row that renders `<label>`
|
|
50
|
-
* around the input).
|
|
51
|
-
*
|
|
52
|
-
* ```vue
|
|
53
|
-
* <!-- Parent -->
|
|
54
|
-
* <MyInput v-register="form.register('email')" />
|
|
55
|
-
*
|
|
56
|
-
* <!-- MyInput.vue -->
|
|
57
|
-
* <script setup lang="ts">
|
|
58
|
-
* import { useRegister } from 'attaform'
|
|
59
|
-
* const rv = useRegister()
|
|
60
|
-
* // rv.path / rv.segments / rv.formKey / rv.formInstanceId / rv.innerRef
|
|
61
|
-
* // are all reachable directly — no `.value` unwrap.
|
|
62
|
-
* </script>
|
|
63
|
-
*
|
|
64
|
-
* <template>
|
|
65
|
-
* <label class="field">
|
|
66
|
-
* <span>Email</span>
|
|
67
|
-
* <input v-register="rv" />
|
|
68
|
-
* </label>
|
|
69
|
-
* </template>
|
|
70
|
-
* ```
|
|
71
|
-
*
|
|
72
|
-
* Returns a hybrid Proxy: it answers `__v_isRef` / `.value` like a
|
|
73
|
-
* Vue `Ref<RegisterValue | undefined>` (so templates auto-unwrap
|
|
74
|
-
* correctly and `v-register="rv"` feeds the underlying RV to the
|
|
75
|
-
* directive — preserving the directive's path-migration diff across
|
|
76
|
-
* renders), AND every other property read pierces to the captured
|
|
77
|
-
* RV's field (so `rv.path` works directly in script setup). Reads
|
|
78
|
-
* inside reactive scopes (`computed` / `watchEffect`) track the
|
|
79
|
-
* underlying `shallowRef`, so `rv.path` re-runs when the parent
|
|
80
|
-
* rebinds to a different path.
|
|
81
|
-
*
|
|
82
|
-
* Unbound state: when the parent didn't pass `v-register`, every
|
|
83
|
-
* piercing read returns `undefined` at runtime, and the return type
|
|
84
|
-
* surfaces this honestly as `UseRegisterReturn<V> | undefined`.
|
|
85
|
-
* Consumers defend with optional chaining (`rv?.formKey`,
|
|
86
|
-
* `rv?.segments`); the directive accepts `undefined` peacefully (its
|
|
87
|
-
* binding value type is already `RegisterValue<V> | undefined`), so
|
|
88
|
-
* `v-register="rv"` works whether or not a parent has bound. The
|
|
89
|
-
* composable's `onMounted` warn fires once per instance to surface
|
|
90
|
-
* the misuse case at runtime.
|
|
91
|
-
*
|
|
92
|
-
* Diagnostic: in dev mode, a single `console.warn` fires per instance
|
|
93
|
-
* at `onMounted` if the captured value is still `undefined` — by then
|
|
94
|
-
* the parent has had its full mount lifecycle to bind, so a missing
|
|
95
|
-
* binding is conclusive misuse. The warn does NOT fire on every read
|
|
96
|
-
* of the proxy, and is intentionally silent under SSR
|
|
97
|
-
* (`renderToString` skips `onMounted`); the CSR hydration pass
|
|
98
|
-
* surfaces the same diagnostic without double-counting through Nuxt's
|
|
99
|
-
* `dev:ssr-logs` channel.
|
|
100
|
-
*
|
|
101
|
-
* When the wrapper's root IS the input itself, Vue's attribute
|
|
102
|
-
* fallthrough handles the binding and `useRegister` is unnecessary.
|
|
103
|
-
* For wrappers that bind multiple fields (compound forms), use
|
|
104
|
-
* `injectForm<Form>(key?)` and call `ctx.register(...)` directly.
|
|
105
|
-
*/
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* Return type of `useRegister()`. Hybrid of `RegisterValue<V>` (so
|
|
109
|
-
* `rv.path` / `rv.segments` / `rv.formKey` etc. work directly in
|
|
110
|
-
* script setup) and `Ref<RegisterValue<V> | undefined>` (so Vue's
|
|
111
|
-
* template auto-unwrap surfaces the underlying RV to `v-register`
|
|
112
|
-
* and the directive's path-migration diff sees the real RV across
|
|
113
|
-
* renders).
|
|
114
|
-
*
|
|
115
|
-
* The two surfaces don't clash at the type level: `RegisterValue`
|
|
116
|
-
* doesn't carry a `value` field, and `Ref<T>`'s `value: T` becomes
|
|
117
|
-
* the hybrid's only `.value`. Older code that read `rv.value?.path`
|
|
118
|
-
* keeps working; new code can write `rv.path` directly.
|
|
119
|
-
*/
|
|
120
|
-
type UseRegisterReturn<V = unknown> = RegisterValue<V> & Ref<RegisterValue<V> | undefined>;
|
|
121
|
-
declare function useRegister<V = unknown>(): UseRegisterReturn<V> | undefined;
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Stable identifiers for library-emitted `ValidationError` codes.
|
|
125
|
-
*
|
|
126
|
-
* Convention: `<scope>:<kebab-case-identifier>`. Three scopes are
|
|
127
|
-
* recognised by the library:
|
|
128
|
-
*
|
|
129
|
-
* - `atta:` — emitted by the framework-agnostic core (this map).
|
|
130
|
-
* - `zod:` — emitted by the Zod adapter; computed inline from
|
|
131
|
-
* `issue.code` (e.g. `zod:too_small`). No enum here because
|
|
132
|
-
* Zod's code list evolves.
|
|
133
|
-
* - consumer-defined — anything the consumer's backend / app stamps
|
|
134
|
-
* onto a `ValidationError` (via the `parseApiErrors` wire payload
|
|
135
|
-
* or `setFieldErrors` directly). Pick a scope (`api:`, `auth:`,
|
|
136
|
-
* etc.) and stay consistent.
|
|
137
|
-
*
|
|
138
|
-
* Use these constants in tests and error-routing UI:
|
|
139
|
-
*
|
|
140
|
-
* ```ts
|
|
141
|
-
* if (error.code === AttaformErrorCode.NoValueSupplied) {
|
|
142
|
-
* // user hasn't filled this field
|
|
143
|
-
* }
|
|
144
|
-
* ```
|
|
145
|
-
*/
|
|
146
|
-
declare const AttaformErrorCode: {
|
|
147
|
-
/** A required field is in the blank set — user hasn't supplied a value. */
|
|
148
|
-
readonly NoValueSupplied: "atta:no-value-supplied";
|
|
149
|
-
/** The schema adapter's `validateAtPath` threw synchronously. */
|
|
150
|
-
readonly AdapterThrew: "atta:adapter-threw";
|
|
151
|
-
/** The supplied path didn't resolve to any node in the schema. */
|
|
152
|
-
readonly PathNotFound: "atta:path-not-found";
|
|
153
|
-
};
|
|
154
|
-
type AttaformErrorCode = (typeof AttaformErrorCode)[keyof typeof AttaformErrorCode];
|
|
155
|
-
|
|
156
|
-
export { AttaformErrorCode as A, injectForm as i, useRegister as u };
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const plugin = require('./attaform.Dee2rU1P.cjs');
|
|
4
|
-
|
|
5
|
-
function renderAttaformState(app) {
|
|
6
|
-
const registry = plugin.getRegistryFromApp(app);
|
|
7
|
-
const forms = [];
|
|
8
|
-
for (const [key, state] of registry.forms) {
|
|
9
|
-
const transientList = Array.from(state.blankPaths);
|
|
10
|
-
forms.push([
|
|
11
|
-
key,
|
|
12
|
-
{
|
|
13
|
-
form: state.form.value,
|
|
14
|
-
schemaErrors: Array.from(state.schemaErrors.entries()),
|
|
15
|
-
userErrors: Array.from(state.userErrors.entries()),
|
|
16
|
-
fields: Array.from(state.fields.entries()),
|
|
17
|
-
...transientList.length > 0 ? { blankPaths: transientList } : {}
|
|
18
|
-
}
|
|
19
|
-
]);
|
|
20
|
-
}
|
|
21
|
-
return { forms };
|
|
22
|
-
}
|
|
23
|
-
function hydrateAttaformState(app, payload) {
|
|
24
|
-
const registry = plugin.getRegistryFromApp(app);
|
|
25
|
-
for (const [key, data] of payload.forms) {
|
|
26
|
-
registry.pendingHydration.set(key, data);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
exports.hydrateAttaformState = hydrateAttaformState;
|
|
31
|
-
exports.renderAttaformState = renderAttaformState;
|
|
32
|
-
//# sourceMappingURL=attaform.C8LVFVVe.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attaform.C8LVFVVe.cjs","sources":["../../src/runtime/core/serialize.ts"],"sourcesContent":["import type { App } from 'vue'\nimport type { FormKey } from '../types/types-api'\nimport { getRegistryFromApp, type SerializedFormData } from './registry'\n\n/**\n * Serialised snapshot of every form in a Vue app, produced by\n * `renderAttaformState` and consumed by `hydrateAttaformState`.\n *\n * JSON-safe — pass to `JSON.stringify`, `devalue`, or any other\n * serialiser before embedding in your SSR payload.\n */\nexport type SerializedAttaformState = {\n /** Tuples of `[formKey, snapshot]` for every form in the app. */\n readonly forms: ReadonlyArray<readonly [FormKey, SerializedFormData]>\n}\n\n/**\n * Snapshot every form on a Vue app for SSR. Call from your server\n * entry after rendering the app:\n *\n * ```ts\n * import { renderToString } from '@vue/server-renderer'\n * import { renderAttaformState, escapeForInlineScript } from 'attaform'\n *\n * const html = await renderToString(app)\n * const state = renderAttaformState(app)\n * const payload = escapeForInlineScript(JSON.stringify(state))\n *\n * return `\n * ${html}\n * <script>window.__ATTAFORM_STATE__ = ${payload}</script>\n * `\n * ```\n *\n * Pair with `hydrateAttaformState` on the client to restore the\n * forms in their server-rendered state. Nuxt users don't need this —\n * `attaform/nuxt` wires SSR automatically.\n */\nexport function renderAttaformState(app: App): SerializedAttaformState {\n const registry = getRegistryFromApp(app)\n const forms: Array<readonly [FormKey, SerializedFormData]> = []\n for (const [key, state] of registry.forms) {\n // Skip the blank field when the set is empty so the\n // wire payload stays minimal for forms that don't use it. The\n // optional shape on the consuming side handles the absence\n // cleanly (defaults to \"no blank paths\").\n const transientList = Array.from(state.blankPaths)\n forms.push([\n key,\n {\n form: state.form.value,\n schemaErrors: Array.from(state.schemaErrors.entries()),\n userErrors: Array.from(state.userErrors.entries()),\n fields: Array.from(state.fields.entries()),\n ...(transientList.length > 0 ? { blankPaths: transientList } : {}),\n },\n ])\n }\n return { forms }\n}\n\n/**\n * Restore forms from a server-rendered snapshot on the client. Call\n * from your client entry before mounting:\n *\n * ```ts\n * import { createApp } from 'vue'\n * import { createAttaform, hydrateAttaformState } from 'attaform'\n *\n * const app = createApp(App).use(createAttaform())\n * hydrateAttaformState(app, window.__ATTAFORM_STATE__)\n * app.mount('#app')\n * ```\n *\n * The next `useForm({ key })` call for each serialised form picks up\n * the snapshot transparently — no further action is required.\n */\nexport function hydrateAttaformState(app: App, payload: SerializedAttaformState): void {\n const registry = getRegistryFromApp(app)\n for (const [key, data] of payload.forms) {\n registry.pendingHydration.set(key, data)\n }\n}\n"],"names":["getRegistryFromApp"],"mappings":";;;;AAsCO,SAAS,oBAAoB,GAAA,EAAmC;AACrE,EAAA,MAAM,QAAA,GAAWA,0BAAmB,GAAG,CAAA;AACvC,EAAA,MAAM,QAAuD,EAAC;AAC9D,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,SAAS,KAAA,EAAO;AAKzC,IAAA,MAAM,aAAA,GAAgB,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,UAAU,CAAA;AACjD,IAAA,KAAA,CAAM,IAAA,CAAK;AAAA,MACT,GAAA;AAAA,MACA;AAAA,QACE,IAAA,EAAM,MAAM,IAAA,CAAK,KAAA;AAAA,QACjB,cAAc,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,YAAA,CAAa,SAAS,CAAA;AAAA,QACrD,YAAY,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,SAAS,CAAA;AAAA,QACjD,QAAQ,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,MAAA,CAAO,SAAS,CAAA;AAAA,QACzC,GAAI,cAAc,MAAA,GAAS,CAAA,GAAI,EAAE,UAAA,EAAY,aAAA,KAAkB;AAAC;AAClE,KACD,CAAA;AAAA,EACH;AACA,EAAA,OAAO,EAAE,KAAA,EAAM;AACjB;AAkBO,SAAS,oBAAA,CAAqB,KAAU,OAAA,EAAwC;AACrF,EAAA,MAAM,QAAA,GAAWA,0BAAmB,GAAG,CAAA;AACvC,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,IAAI,CAAA,IAAK,QAAQ,KAAA,EAAO;AACvC,IAAA,QAAA,CAAS,gBAAA,CAAiB,GAAA,CAAI,GAAA,EAAK,IAAI,CAAA;AAAA,EACzC;AACF;;;;;"}
|