vitral 0.1.0 → 0.2.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.
Files changed (56) hide show
  1. package/README.md +250 -217
  2. package/dist/angular.d.ts +15 -4
  3. package/dist/angular.js +25 -5
  4. package/dist/auto.d.ts +2 -0
  5. package/dist/auto.js +12 -0
  6. package/dist/chunk-2XF5BKV3.js +190 -0
  7. package/dist/chunk-6Y3VMWHH.js +181 -0
  8. package/dist/chunk-DXORSF4X.js +42 -0
  9. package/dist/chunk-GNPFWISJ.js +80 -0
  10. package/dist/chunk-HP6QWU6K.js +51 -0
  11. package/dist/chunk-NCONW6WS.js +606 -0
  12. package/dist/chunk-PX7PBCCT.js +89 -0
  13. package/dist/chunk-S5MZT5IT.js +20 -0
  14. package/dist/chunk-SFL6LTP3.js +56 -0
  15. package/dist/chunk-UTYAX6MU.js +152 -0
  16. package/dist/cli.d.ts +1 -0
  17. package/dist/cli.js +88 -0
  18. package/dist/dedupe-IWFIXRWG.js +81 -0
  19. package/dist/devtools.d.ts +12 -0
  20. package/dist/devtools.js +86 -0
  21. package/dist/element.d.ts +60 -2
  22. package/dist/element.js +9 -2
  23. package/dist/errors-KKB8FGCz.d.ts +11 -0
  24. package/dist/events-DUdjhfps.d.ts +6 -0
  25. package/dist/expose-53BEJB34.js +14 -0
  26. package/dist/host-slot-Cz6EiGsB.d.ts +6 -0
  27. package/dist/iframe.d.ts +28 -0
  28. package/dist/iframe.js +236 -0
  29. package/dist/index.d.ts +142 -147
  30. package/dist/index.js +39 -10
  31. package/dist/navigate-BRG1WJUM.d.ts +9 -0
  32. package/dist/overrides-NZAIUGK5.js +15 -0
  33. package/dist/preact.d.ts +30 -7
  34. package/dist/preact.js +37 -9
  35. package/dist/react.d.ts +38 -7
  36. package/dist/react.js +92 -42
  37. package/dist/routes.d.ts +56 -0
  38. package/dist/routes.js +143 -0
  39. package/dist/shadow-MYRJQLLY.js +72 -0
  40. package/dist/slot-pB276oPt.d.ts +36 -0
  41. package/dist/solid.d.ts +29 -6
  42. package/dist/solid.js +31 -8
  43. package/dist/sri-BVKZNX5Q.js +114 -0
  44. package/dist/state-BDdCwc21.d.ts +4 -0
  45. package/dist/svelte.d.ts +19 -3
  46. package/dist/svelte.js +10 -4
  47. package/dist/testing.d.ts +2 -2
  48. package/dist/testing.js +8 -3
  49. package/dist/types-BV-hUrms.d.ts +265 -0
  50. package/dist/vite.d.ts +58 -4
  51. package/dist/vite.js +714 -24
  52. package/dist/vue.d.ts +79 -7
  53. package/dist/vue.js +69 -46
  54. package/package.json +144 -8
  55. package/dist/chunk-IZK6ITIJ.js +0 -96
  56. package/dist/chunk-TTL52BF2.js +0 -547
package/dist/vue.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import * as vue from 'vue';
2
- import { PropType, App, ShallowRef, Component } from 'vue';
3
- import { Props, Isolation, RemoteContext, RemoteModule } from './index.js';
4
- export { events } from './index.js';
2
+ import { PropType, App, ShallowRef, WritableComputedRef, ComputedRef, Component } from 'vue';
3
+ import { P as Props, I as Isolation, R as RemoteContext, S as Shared, a as RemoteModule } from './types-BV-hUrms.js';
4
+ export { e as events } from './events-DUdjhfps.js';
5
+ import { L as Loading, P as Prefetch } from './host-slot-Cz6EiGsB.js';
5
6
 
6
7
  interface VueRemoteOptions {
7
8
  /** Instale plugins (router, pinia, i18n…) no app do remote. */
@@ -15,6 +16,19 @@ declare function useVitral(): RemoteContext | null;
15
16
  declare function useEvent<T = unknown>(type: string, handler: (payload: T) => void): void;
16
17
  /** Ref com o último valor emitido em `type`. */
17
18
  declare function useEventValue<T = unknown>(type: string): ShallowRef<T | undefined>;
19
+ /**
20
+ * Ref de uma chave compartilhada (`provide`/`shared`). Sem seletor, a ref
21
+ * também escreve (`usuario.value = …` chama `set`, e `v-model` funciona). Com
22
+ * seletor, é só leitura e só muda quando o resultado muda (`Object.is`). A
23
+ * assinatura acaba junto com o componente (ou o `effectScope`).
24
+ *
25
+ * const usuario = useShared('usuario')
26
+ * const nome = useShared('usuario', (u) => u?.nome)
27
+ */
28
+ declare function useShared<K extends keyof Shared>(key: K): WritableComputedRef<Shared[K] | undefined>;
29
+ declare function useShared<K extends keyof Shared, S>(key: K, select: (value: Shared[K] | undefined) => S): ComputedRef<S>;
30
+ declare function useShared<T = unknown>(key: string): WritableComputedRef<T | undefined>;
31
+ declare function useShared<T, S>(key: string, select: (value: T | undefined) => S): ComputedRef<S>;
18
32
 
19
33
  /**
20
34
  * Renderiza um remote. No servidor (Nuxt SSR) renderiza só o slot `fallback`;
@@ -23,9 +37,15 @@ declare function useEventValue<T = unknown>(type: string): ShallowRef<T | undefi
23
37
  * Slots: `fallback` (carregando) e `error` ({ error, retry }).
24
38
  */
25
39
  declare const VitralRemote: vue.DefineComponent<vue.ExtractPropTypes<{
40
+ /** Nome registrado. Com `src`, o nome sob o qual a URL é registrada. */
26
41
  name: {
27
42
  type: StringConstructor;
28
- required: true;
43
+ default: undefined;
44
+ };
45
+ /** URL do `vitral.json`. Dispensa `configure()`. */
46
+ src: {
47
+ type: StringConstructor;
48
+ default: undefined;
29
49
  };
30
50
  props: {
31
51
  type: PropType<Props>;
@@ -35,12 +55,38 @@ declare const VitralRemote: vue.DefineComponent<vue.ExtractPropTypes<{
35
55
  type: PropType<Isolation>;
36
56
  default: undefined;
37
57
  };
58
+ /** `'lazy'`: monta perto de aparecer na tela; `'idle'`: com o navegador ocioso. */
59
+ loading: {
60
+ type: PropType<Loading>;
61
+ default: undefined;
62
+ };
63
+ /** Baixa antes de montar: `'hover'`, `'visible'` ou `'idle'`. */
64
+ prefetch: {
65
+ type: PropType<Prefetch>;
66
+ default: undefined;
67
+ };
68
+ /** `'high'` para o remote que aparece logo ao abrir a página. */
69
+ priority: {
70
+ type: PropType<RequestPriority>;
71
+ default: undefined;
72
+ };
73
+ /** Ao sair da página, guarda o remote montado (LRU, padrão 5) e na volta só atualiza as props. */
74
+ keepAlive: {
75
+ type: (NumberConstructor | BooleanConstructor)[];
76
+ default: boolean;
77
+ };
38
78
  }>, () => vue.VNode<vue.RendererNode, vue.RendererElement, {
39
79
  [key: string]: any;
40
80
  }>, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, ("error" | "ready")[], "error" | "ready", vue.PublicProps, Readonly<vue.ExtractPropTypes<{
81
+ /** Nome registrado. Com `src`, o nome sob o qual a URL é registrada. */
41
82
  name: {
42
83
  type: StringConstructor;
43
- required: true;
84
+ default: undefined;
85
+ };
86
+ /** URL do `vitral.json`. Dispensa `configure()`. */
87
+ src: {
88
+ type: StringConstructor;
89
+ default: undefined;
44
90
  };
45
91
  props: {
46
92
  type: PropType<Props>;
@@ -50,12 +96,38 @@ declare const VitralRemote: vue.DefineComponent<vue.ExtractPropTypes<{
50
96
  type: PropType<Isolation>;
51
97
  default: undefined;
52
98
  };
99
+ /** `'lazy'`: monta perto de aparecer na tela; `'idle'`: com o navegador ocioso. */
100
+ loading: {
101
+ type: PropType<Loading>;
102
+ default: undefined;
103
+ };
104
+ /** Baixa antes de montar: `'hover'`, `'visible'` ou `'idle'`. */
105
+ prefetch: {
106
+ type: PropType<Prefetch>;
107
+ default: undefined;
108
+ };
109
+ /** `'high'` para o remote que aparece logo ao abrir a página. */
110
+ priority: {
111
+ type: PropType<RequestPriority>;
112
+ default: undefined;
113
+ };
114
+ /** Ao sair da página, guarda o remote montado (LRU, padrão 5) e na volta só atualiza as props. */
115
+ keepAlive: {
116
+ type: (NumberConstructor | BooleanConstructor)[];
117
+ default: boolean;
118
+ };
53
119
  }>> & Readonly<{
54
120
  onError?: ((...args: any[]) => any) | undefined;
55
121
  onReady?: ((...args: any[]) => any) | undefined;
56
122
  }>, {
57
- props: Props;
58
123
  isolate: Isolation;
124
+ name: string;
125
+ priority: RequestPriority;
126
+ loading: Loading;
127
+ src: string;
128
+ props: Props;
129
+ prefetch: Prefetch;
130
+ keepAlive: number | boolean;
59
131
  }, {}, {}, {}, string, vue.ComponentProvideOptions, true, {}, any>;
60
132
 
61
- export { VitralRemote, type VueRemoteOptions, useEvent, useEventValue, useVitral, vueRemote };
133
+ export { VitralRemote, type VueRemoteOptions, useEvent, useEventValue, useShared, useVitral, vueRemote };
package/dist/vue.js CHANGED
@@ -1,17 +1,32 @@
1
+ import {
2
+ hostSlot,
3
+ timings
4
+ } from "./chunk-UTYAX6MU.js";
1
5
  import {
2
6
  defineRemote,
3
7
  events,
4
- mountRemote
5
- } from "./chunk-TTL52BF2.js";
8
+ memoSelect,
9
+ same,
10
+ shared
11
+ } from "./chunk-NCONW6WS.js";
12
+ import "./chunk-2XF5BKV3.js";
13
+ import "./chunk-SFL6LTP3.js";
14
+ import {
15
+ absolute
16
+ } from "./chunk-PX7PBCCT.js";
17
+ import "./chunk-GNPFWISJ.js";
6
18
 
7
19
  // src/vue.ts
8
20
  import {
21
+ computed,
9
22
  createApp,
10
23
  defineComponent,
24
+ getCurrentScope,
11
25
  h,
12
26
  inject,
13
27
  onBeforeUnmount,
14
28
  onMounted,
29
+ onScopeDispose,
15
30
  ref,
16
31
  shallowReactive,
17
32
  shallowRef,
@@ -50,68 +65,75 @@ function useEventValue(type) {
50
65
  useEvent(type, (v) => value.value = v);
51
66
  return value;
52
67
  }
68
+ function useShared(key, select) {
69
+ const handle = shared(key);
70
+ const pick = memoSelect();
71
+ const state = shallowRef();
72
+ const off = handle.subscribe((v) => state.value = pick(v, select ?? same));
73
+ if (getCurrentScope()) onScopeDispose(off);
74
+ return select ? computed(() => state.value) : computed({ get: () => state.value, set: handle.set });
75
+ }
53
76
  var VitralRemote = defineComponent({
54
77
  name: "VitralRemote",
55
78
  props: {
56
- name: { type: String, required: true },
79
+ /** Nome registrado. Com `src`, o nome sob o qual a URL é registrada. */
80
+ name: { type: String, default: void 0 },
81
+ /** URL do `vitral.json`. Dispensa `configure()`. */
82
+ src: { type: String, default: void 0 },
57
83
  props: { type: Object, default: () => ({}) },
58
- isolate: { type: String, default: void 0 }
84
+ isolate: { type: String, default: void 0 },
85
+ /** `'lazy'`: monta perto de aparecer na tela; `'idle'`: com o navegador ocioso. */
86
+ loading: { type: String, default: void 0 },
87
+ /** Baixa antes de montar: `'hover'`, `'visible'` ou `'idle'`. */
88
+ prefetch: { type: String, default: void 0 },
89
+ /** `'high'` para o remote que aparece logo ao abrir a página. */
90
+ priority: { type: String, default: void 0 },
91
+ /** Ao sair da página, guarda o remote montado (LRU, padrão 5) e na volta só atualiza as props. */
92
+ keepAlive: { type: [Boolean, Number], default: false }
59
93
  },
60
94
  emits: ["error", "ready"],
61
95
  setup(p, { slots, emit }) {
62
- const slot = ref(null);
96
+ const target = ref(null);
63
97
  const status = ref("loading");
64
98
  const error = shallowRef(null);
65
- const attempt = ref(0);
66
- let handle = null;
67
- let token = 0;
68
- function fail(e, my) {
69
- if (my !== token) return;
70
- error.value = e;
71
- status.value = "error";
72
- emit("error", e);
73
- if (!slots.error) console.error(e);
74
- }
75
- async function mount() {
76
- const my = ++token;
77
- handle?.unmount();
78
- handle = null;
79
- status.value = "loading";
80
- try {
81
- const onError = (e) => fail(e, my);
82
- const initial = p.props;
83
- const h2 = await mountRemote(slot.value, p.name, { ...initial }, { isolate: p.isolate, onError });
84
- if (my !== token) return h2.unmount();
85
- handle = h2;
86
- if (p.props !== initial) h2.update?.({ ...p.props });
87
- status.value = "ready";
88
- emit("ready");
89
- } catch (e) {
90
- fail(e, my);
91
- }
92
- }
93
- onMounted(mount);
94
- watch(() => [p.name, p.isolate, attempt.value], mount, { flush: "post" });
99
+ let slot = null;
100
+ onMounted(() => {
101
+ slot = hostSlot(target.value, {
102
+ name: p.name,
103
+ src: p.src,
104
+ props: { ...p.props },
105
+ isolate: p.isolate,
106
+ loading: p.loading,
107
+ prefetch: p.prefetch,
108
+ priority: p.priority,
109
+ keepAlive: p.keepAlive,
110
+ onStatus(s, e) {
111
+ status.value = s;
112
+ error.value = e;
113
+ if (s === "ready") emit("ready", timings(p.name || absolute(p.src ?? "")));
114
+ if (e) {
115
+ emit("error", e);
116
+ if (!slots.error) console.error(e);
117
+ }
118
+ }
119
+ });
120
+ });
121
+ watch(() => [p.name, p.src, p.isolate], ([name, src, isolate]) => slot?.set({ name, src, isolate }), { flush: "post" });
95
122
  watch(
96
123
  () => p.props,
97
- (next) => handle?.update?.({ ...next }),
124
+ (next) => slot?.update({ ...next }),
98
125
  { deep: true }
99
126
  );
100
127
  onBeforeUnmount(() => {
101
- token++;
102
- handle?.unmount();
103
- handle = null;
128
+ slot?.destroy();
129
+ slot = null;
104
130
  });
105
- const retry = () => attempt.value++;
106
- return () => h("div", { "data-vitral": p.name, "data-vitral-status": status.value }, [
131
+ const retry = () => slot?.retry();
132
+ return () => h("div", { "data-vitral": p.name ?? p.src, "data-vitral-status": status.value }, [
107
133
  status.value === "loading" ? slots.fallback?.() : null,
108
134
  status.value === "error" ? slots.error?.({ error: error.value, retry }) : null,
109
135
  // O Vue nunca coloca filhos neste div: ele pertence ao remote.
110
- h("div", {
111
- key: `${p.name}:${p.isolate}:${attempt.value}`,
112
- ref: slot,
113
- style: status.value === "error" ? "display:none" : void 0
114
- })
136
+ h("div", { ref: target })
115
137
  ]);
116
138
  }
117
139
  });
@@ -120,6 +142,7 @@ export {
120
142
  events,
121
143
  useEvent,
122
144
  useEventValue,
145
+ useShared,
123
146
  useVitral,
124
147
  vueRemote
125
148
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vitral",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Micro-frontends sem burocracia: um contrato mount/unmount, carregamento em runtime e adaptadores para React, Next, Vue, Nuxt, Angular, Svelte, Solid, Preact, Lit e JS/TS puro.",
5
5
  "keywords": [
6
6
  "micro-frontend",
@@ -31,9 +31,14 @@
31
31
  "license": "MIT",
32
32
  "author": "João (https://github.com/joaogabriel15)",
33
33
  "type": "module",
34
- "sideEffects": false,
34
+ "bin": {
35
+ "vitral": "./dist/cli.js"
36
+ },
37
+ "sideEffects": [
38
+ "./dist/auto.js"
39
+ ],
35
40
  "engines": {
36
- "node": ">=18"
41
+ "node": ">=20.19"
37
42
  },
38
43
  "files": [
39
44
  "dist",
@@ -45,10 +50,26 @@
45
50
  "types": "./dist/index.d.ts",
46
51
  "import": "./dist/index.js"
47
52
  },
53
+ "./auto": {
54
+ "types": "./dist/auto.d.ts",
55
+ "import": "./dist/auto.js"
56
+ },
57
+ "./devtools": {
58
+ "types": "./dist/devtools.d.ts",
59
+ "import": "./dist/devtools.js"
60
+ },
48
61
  "./element": {
49
62
  "types": "./dist/element.d.ts",
50
63
  "import": "./dist/element.js"
51
64
  },
65
+ "./routes": {
66
+ "types": "./dist/routes.d.ts",
67
+ "import": "./dist/routes.js"
68
+ },
69
+ "./iframe": {
70
+ "types": "./dist/iframe.d.ts",
71
+ "import": "./dist/iframe.js"
72
+ },
52
73
  "./react": {
53
74
  "types": "./dist/react.d.ts",
54
75
  "import": "./dist/react.js"
@@ -97,6 +118,7 @@
97
118
  "react-dom": ">=18",
98
119
  "solid-js": ">=1.8",
99
120
  "svelte": ">=5",
121
+ "typescript": ">=5",
100
122
  "vite": ">=5",
101
123
  "vue": ">=3.3"
102
124
  },
@@ -127,6 +149,9 @@
127
149
  },
128
150
  "vite": {
129
151
  "optional": true
152
+ },
153
+ "typescript": {
154
+ "optional": true
130
155
  }
131
156
  },
132
157
  "devDependencies": {
@@ -137,10 +162,12 @@
137
162
  "@arethetypeswrong/cli": "^0.18.5",
138
163
  "@size-limit/preset-small-lib": "^11.2.0",
139
164
  "@sveltejs/vite-plugin-svelte": "^7.3.1",
165
+ "@tailwindcss/vite": "^4.3.3",
140
166
  "@testing-library/dom": "^10.4.2",
141
167
  "@types/node": "^22.20.5",
142
168
  "@types/react": "^19.0.0",
143
169
  "@types/react-dom": "^19.0.0",
170
+ "@vitest/coverage-v8": "4.1.11",
144
171
  "happy-dom": "^20.0.0",
145
172
  "preact": "^10.29.8",
146
173
  "publint": "^0.3.25",
@@ -150,6 +177,7 @@
150
177
  "size-limit": "^11.2.0",
151
178
  "solid-js": "^1.9.17",
152
179
  "svelte": "^5.57.2",
180
+ "tailwindcss": "^4.3.3",
153
181
  "tsup": "^8.5.0",
154
182
  "typescript": "~5.9.0",
155
183
  "vite": "^8.0.0",
@@ -157,27 +185,99 @@
157
185
  "vue": "^3.5.0"
158
186
  },
159
187
  "size-limit": [
188
+ {
189
+ "name": "host mínimo",
190
+ "path": "dist/index.js",
191
+ "import": "{ configure, createSlot }",
192
+ "ignore": [
193
+ "./shadow-*",
194
+ "./overrides-*",
195
+ "./sri-*",
196
+ "./dedupe-*",
197
+ "./expose-*"
198
+ ],
199
+ "limit": "4.3 kB"
200
+ },
160
201
  {
161
202
  "name": "núcleo",
162
203
  "path": "dist/index.js",
204
+ "import": "{ RemoteError, __reset, component, configure, createEventBus, createSlot, defineRemote, events, html, loadRemote, mountRemote, navigate, preload, register, render, unsafeHTML }",
205
+ "ignore": [
206
+ "./shadow-*",
207
+ "./sri-*",
208
+ "./dedupe-*",
209
+ "./expose-*"
210
+ ],
211
+ "limit": "5.4 kB"
212
+ },
213
+ {
214
+ "name": "SRI e dedupe (sob demanda, com as dependências)",
215
+ "path": "dist/sri-*.js",
216
+ "limit": "2.4 kB"
217
+ },
218
+ {
219
+ "name": "dedupe (sob demanda, para hosts que oferecem dependências)",
220
+ "path": "dist/dedupe-*.js",
221
+ "limit": "0.65 kB"
222
+ },
223
+ {
224
+ "name": "host mínimo + store",
225
+ "path": "dist/index.js",
226
+ "import": "{ configure, createSlot, provide, shared, batch }",
227
+ "ignore": [
228
+ "./shadow-*",
229
+ "./overrides-*",
230
+ "./sri-*",
231
+ "./dedupe-*",
232
+ "./expose-*"
233
+ ],
163
234
  "limit": "5 kB"
164
235
  },
236
+ {
237
+ "name": "host mínimo + store + persist + syncTabs",
238
+ "path": "dist/index.js",
239
+ "import": "{ configure, createSlot, provide, shared, batch, persist, syncTabs }",
240
+ "ignore": [
241
+ "./shadow-*",
242
+ "./overrides-*",
243
+ "./sri-*",
244
+ "./dedupe-*",
245
+ "./expose-*"
246
+ ],
247
+ "limit": "5.2 kB"
248
+ },
249
+ {
250
+ "name": "estilos do Shadow DOM (além do núcleo)",
251
+ "path": "dist/shadow-*.js",
252
+ "ignore": [
253
+ "./chunk-*"
254
+ ],
255
+ "limit": "1 kB"
256
+ },
165
257
  {
166
258
  "name": "react",
167
259
  "path": "dist/react.js",
168
260
  "import": "{ Remote, reactRemote }",
169
261
  "ignore": [
170
262
  "react",
171
- "react-dom"
263
+ "react-dom",
264
+ "./shadow-*",
265
+ "./sri-*",
266
+ "./dedupe-*",
267
+ "./expose-*"
172
268
  ],
173
- "limit": "6 kB"
269
+ "limit": "6.2 kB"
174
270
  },
175
271
  {
176
272
  "name": "vue",
177
273
  "path": "dist/vue.js",
178
274
  "import": "{ VitralRemote, vueRemote }",
179
275
  "ignore": [
180
- "vue"
276
+ "vue",
277
+ "./shadow-*",
278
+ "./sri-*",
279
+ "./dedupe-*",
280
+ "./expose-*"
181
281
  ],
182
282
  "limit": "6 kB"
183
283
  },
@@ -185,13 +285,49 @@
185
285
  "name": "element",
186
286
  "path": "dist/element.js",
187
287
  "import": "{ defineVitralElement }",
288
+ "ignore": [
289
+ "./shadow-*",
290
+ "./sri-*",
291
+ "./dedupe-*",
292
+ "./expose-*"
293
+ ],
294
+ "limit": "6.1 kB"
295
+ },
296
+ {
297
+ "name": "devtools",
298
+ "path": "dist/devtools.js",
299
+ "import": "{ devtools }",
300
+ "limit": "2 kB"
301
+ },
302
+ {
303
+ "name": "auto",
304
+ "path": "dist/auto.js",
305
+ "limit": "6 kB",
306
+ "ignore": [
307
+ "./shadow-*",
308
+ "./overrides-*",
309
+ "./sri-*",
310
+ "./dedupe-*",
311
+ "./expose-*"
312
+ ]
313
+ },
314
+ {
315
+ "name": "routes",
316
+ "path": "dist/routes.js",
317
+ "import": "{ routes }",
318
+ "limit": "7.9 kB"
319
+ },
320
+ {
321
+ "name": "iframe",
322
+ "path": "dist/iframe.js",
323
+ "import": "{ enableIframe }",
188
324
  "limit": "6 kB"
189
325
  }
190
326
  ],
191
327
  "scripts": {
192
328
  "build": "tsup",
193
- "test": "vitest run",
194
- "typecheck": "tsc --noEmit",
329
+ "test": "vitest run --coverage",
330
+ "typecheck": "tsc --noEmit && tsc -p test/types",
195
331
  "lint:pkg": "publint --strict && attw --pack --profile esm-only",
196
332
  "size": "size-limit"
197
333
  }
@@ -1,96 +0,0 @@
1
- import {
2
- createSlot,
3
- defineRemote
4
- } from "./chunk-TTL52BF2.js";
5
-
6
- // src/element.ts
7
- var Base = typeof HTMLElement === "undefined" ? class {
8
- } : HTMLElement;
9
- var VitralRemoteElement = class extends Base {
10
- static {
11
- this.observedAttributes = ["name", "props", "isolate"];
12
- }
13
- #slot = null;
14
- #props = {};
15
- get props() {
16
- return this.#props;
17
- }
18
- set props(value) {
19
- this.#props = value ?? {};
20
- this.#slot?.update(this.#props);
21
- }
22
- get status() {
23
- return this.#slot?.status ?? "loading";
24
- }
25
- retry() {
26
- this.#slot?.retry();
27
- }
28
- connectedCallback() {
29
- if (this.#slot) return;
30
- const name = this.getAttribute("name");
31
- if (!name) return;
32
- if (this.hasAttribute("props") && !Object.keys(this.#props).length) this.#props = parseProps(this.getAttribute("props"));
33
- this.#slot = createSlot(this, {
34
- name,
35
- props: this.#props,
36
- isolate: this.getAttribute("isolate") || void 0,
37
- onStatus: (status, error) => {
38
- this.setAttribute("data-vitral-status", status);
39
- for (const el of this.querySelectorAll(':scope > [slot="fallback"]')) el.hidden = status !== "loading";
40
- for (const el of this.querySelectorAll(':scope > [slot="error"]')) el.hidden = status !== "error";
41
- if (status === "ready") this.dispatchEvent(new CustomEvent("vitral-ready", { bubbles: true }));
42
- if (status === "error") this.dispatchEvent(new CustomEvent("vitral-error", { bubbles: true, detail: { error } }));
43
- }
44
- });
45
- }
46
- disconnectedCallback() {
47
- queueMicrotask(() => {
48
- if (!this.isConnected) {
49
- this.#slot?.destroy();
50
- this.#slot = null;
51
- }
52
- });
53
- }
54
- attributeChangedCallback(attr, _old, value) {
55
- if (attr === "props") return void (this.props = parseProps(value));
56
- if (!this.#slot) return void (this.isConnected && this.connectedCallback());
57
- if (attr === "name" && value) this.#slot.set({ name: value });
58
- if (attr === "isolate") this.#slot.set({ isolate: value || void 0 });
59
- }
60
- };
61
- function parseProps(value) {
62
- if (!value) return {};
63
- try {
64
- return JSON.parse(value);
65
- } catch {
66
- console.error("[vitral] atributo props n\xE3o \xE9 JSON v\xE1lido:", value);
67
- return {};
68
- }
69
- }
70
- function defineVitralElement(tag = "vitral-remote") {
71
- if (typeof customElements !== "undefined" && !customElements.get(tag)) {
72
- customElements.define(tag, class extends VitralRemoteElement {
73
- });
74
- }
75
- }
76
- function elementRemote(tag, setup) {
77
- return defineRemote({
78
- mount(el, props, ctx) {
79
- setup?.();
80
- const node = document.createElement(tag);
81
- node.vitral = ctx;
82
- Object.assign(node, props);
83
- el.appendChild(node);
84
- return {
85
- update: (next) => Object.assign(node, next),
86
- unmount: () => node.remove()
87
- };
88
- }
89
- });
90
- }
91
-
92
- export {
93
- VitralRemoteElement,
94
- defineVitralElement,
95
- elementRemote
96
- };