@jsweb/ui 1.3.0 → 1.3.2

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/dist/README.md DELETED
@@ -1,227 +0,0 @@
1
- # @jsweb/ui
2
-
3
- ## Introdução
4
-
5
- O `@jsweb/ui` é um micro-framework frontend escrito em TypeScript, projetado para ser uma ferramenta leve, rápida e flexível para o desenvolvimento de interfaces de usuário. Ele combina a reatividade moderna de frameworks como Vue 3 (Composition API) com a simplicidade de uso direto no HTML, semelhante ao Alpine.js.
6
-
7
- ### Pilares Arquiteturais
8
-
9
- - **Sem Virtual DOM**: Utiliza reatividade de grão fino (Fine-grained reactivity) via `Proxy` para atualizações diretas no DOM real.
10
- - **Distribuição Dupla**:
11
- - **Standalone**: Arquivo único (IIFE/UMD) para inclusão via `<script src="...">`.
12
- - **Module**: Pacote ESM com exports nomeados para suporte a Tree-Shaking.
13
- - **Contexto Híbrido**: Suporta definição de estado via Objetos Literais (POJOs) ou Classes TypeScript.
14
- - **Template Engine**: Baseado em atributos customizados no HTML (`ui:*` para diretivas e `ui@*` para eventos, com shorthands `@`, `:`).
15
- - Suporte completo a **modificadores de eventos** encadeados (`.prevent`, `.stop`, `.self`, `.outside`).
16
-
17
- ## Instalação
18
-
19
- ### NPM
20
-
21
- ```bash
22
- npm i @jsweb/ui
23
- ```
24
-
25
- ### CDN
26
-
27
- ```html
28
- <script src="https://unpkg.com/@jsweb/ui"></script>
29
- ```
30
-
31
- ## Diretivas Disponíveis
32
-
33
- O framework utiliza um sistema de atributos customizados para declaratividade no HTML, suportando tanto o prefixo completo (`ui:`, `ui@`) quanto a sintaxe simplificada (`:`, `@`).
34
-
35
- | Diretiva | Atalho | Descrição | Exemplo |
36
- | :----------- | :--------- | :-------------------------------------------------------------------------------- | :----------------------------------------- |
37
- | `ui:scope` | `:scope` | Define o objeto de estado/contexto para o elemento e seus filhos. | `<div :scope="{ count: 0 }">` |
38
- | `ui:text` | `:text` | Sincroniza o `textContent` com uma variável ou expressão. | `<span :text="count"></span>` |
39
- | `ui:bind` | `:bind` | Two-way data binding para inputs, checkboxes, radios, selects e textarea. | `<input :bind="name">` |
40
- | `ui:if` | `:if` | Renderização condicional no DOM (via Comment Node placeholder). | `<div :if="count > 0">` |
41
- | `ui:for` | `:for` | Renderiza listas com suporte a `in` e `of`, expondo `$index`. | `<li :for="item of items">` |
42
- | `ui:key` | `:key` | Identificador único para reconciliação e reciclagem eficiente de nós DOM. | `<li :for="item of items" :key="item.id">` |
43
- | `ui:class` | `:class` | Bind reativo para classes CSS (suporta String, Array ou Objeto booleano). | `<div :class="{ active: isActive }">` |
44
- | `ui:style` | `:style` | Bind reativo para estilos inline (recebe objeto chave/valor de propriedades CSS). | `<div :style="{ color: textColor }">` |
45
- | `ui:ref` | `:ref` | Referencia elementos HTML indexados em um Map acessível via `$refs`. | `<input :ref="myInput">` |
46
- | `ui:[attr]` | `:[attr]` | Bind de atributos HTML nativos (remove se falsy, ativa se booleano `true`). | `<button :disabled="count > 10">` |
47
- | `ui@[event]` | `@[event]` | Escuta eventos DOM nativos ou customizados (com suporte a modificadores). | `<button @click.prevent="save">` |
48
-
49
- ### Modificadores de Eventos
50
-
51
- É possível encadear modificadores diretamente na sintaxe do evento (`@event.modificador` ou `ui@event.modificador`):
52
-
53
- - **`.prevent`**: Executa `$event.preventDefault()`.
54
- - **`.stop`**: Executa `$event.stopPropagation()`.
55
- - **`.self`**: Dispara o manipulador apenas quando o evento se originou exatamente no próprio elemento (`$event.target === el`).
56
- - **`.outside`**: Dispara quando o evento ocorre fora do elemento (ideal para fechar menus, modais e dropdowns). Gerencia o ouvinte no `document` com remoção e limpeza automáticas quando o elemento for desconectado.
57
-
58
- ### Variáveis e Helpers de Contexto
59
-
60
- Dentro das expressões declaradas no HTML, o framework disponibiliza variáveis e métodos contextuais:
61
-
62
- - **`$refs`**: Objeto `Map` nativo contendo as referências registradas via `ui:ref` / `:ref`. Em elementos simples, retorna diretamente o elemento (`this.$refs.get('name')`). Em elementos dentro de loops `ui:for` com `:key`, retorna um `Map` aninhado indexado pela chave (`this.$refs.get('name').get($key)`).
63
- - **`$emit(eventName, detail?)`**: Função injetada em todos os escopos para disparar `CustomEvent` nativos (`bubbles: true`, `composed: true`), facilitando a comunicação com elementos ancestrais (`@custom-event="handle"`).
64
- - **`$event`**: Objeto nativo do evento disparado, disponível nas expressões de manipuladores (`@click="handle($event)"`). Se você referenciar apenas a função (`@click="handle"`), ela receberá `$event` automaticamente como primeiro argumento.
65
- - **`$index`**: Índice numérico (base 0) da iteração atual, disponível dentro do escopo de um `ui:for` / `:for`.
66
-
67
- ### Detalhes de Comportamento
68
-
69
- #### Two-Way Data Binding (`ui:bind` / `:bind`)
70
-
71
- Detecta e trata o elemento de acordo com seu tipo:
72
-
73
- - **`input[type="checkbox"]`**: Sincroniza a propriedade booleana `checked` e atualiza no evento `change`.
74
- - **`input[type="radio"]`**: Marca como selecionado caso `el.value === String(valor)` e atualiza no evento `change`.
75
- - **`<select>`**: Sincroniza o `value` selecionado e escuta o evento `change`.
76
- - **`<input>` (texto, número, cor, data, etc.) e `<textarea>`**: Sincroniza `value` e atualiza em tempo real no evento `input`.
77
-
78
- #### Classes Dinâmicas (`ui:class` / `:class`)
79
-
80
- Atualiza classes reativas preservando classes estáticas já presentes no elemento:
81
-
82
- - **Objeto**: `:class="{ active: isActive, 'has-error': error }"`
83
- - **Array**: `:class="['badge', isActive && 'badge-success']"`
84
- - **String**: `:class="currentClass"`
85
-
86
- #### Reconciliação Inteligente em Listas (`ui:for` / `:for` e `ui:key` / `:key`)
87
-
88
- ```html
89
- <ul>
90
- <li :for="item of items" :key="item.id">
91
- <span :text="$index"></span>: <strong :text="item.title"></strong>
92
- </li>
93
- </ul>
94
- ```
95
-
96
- Ao atualizar arrays reativos, o motor rastreia os nós pelo `:key` (ou índice por padrão) e reaproveita as instâncias existentes no DOM, evitando reflows desnecessários e mantendo estados de foco/interação.
97
-
98
- #### Referências a Elementos (`ui:ref` / `:ref` e `$refs`)
99
-
100
- O atributo `ui:ref` ou `:ref` indexa o elemento diretamente em um objeto `Map` acessível via `this.$refs` em métodos ou `$refs` em templates:
101
-
102
- 1. **Uso Simples (Elemento Único)**:
103
-
104
- ```html
105
- <input type="text" :ref="searchBox" />
106
- <button @click="$refs.get('searchBox').focus()">Focar</button>
107
- ```
108
-
109
- No código do componente:
110
-
111
- ```javascript
112
- this.$refs.get('searchBox').focus()
113
- ```
114
-
115
- 2. **Uso em Listas (`ui:for` com `:key`)**:
116
- Quando utilizado dentro de um loop com `:key`, o framework cria automaticamente um `Map` aninhado mapeando cada elemento pela chave do item:
117
-
118
- ```html
119
- <ul>
120
- <li :for="user of users" :key="user.id">
121
- <input type="text" :value="user.name" :ref="userInput" />
122
- </li>
123
- </ul>
124
- ```
125
-
126
- Para resgatar o elemento de um item específico:
127
-
128
- ```javascript
129
- const input = this.$refs.get('userInput').get(user.id)
130
- input?.focus()
131
- ```
132
-
133
- 3. **Limpeza Automática**:
134
- Quando um elemento referenciado sai do DOM (seja por remoção do item em lista ou por `ui:if`), ele é desregistrado automaticamente do `Map`, evitando vazamentos de memória e referências a nós órfãos.
135
-
136
- ## Exemplo de Uso
137
-
138
- ### HTML
139
-
140
- ```html
141
- <!DOCTYPE html>
142
- <html lang="en">
143
- <head>
144
- <meta charset="UTF-8" />
145
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
146
- <title>JS Web UI</title>
147
- <script src="https://unpkg.com/@jsweb/ui"></script>
148
- <script>
149
- const scope = {
150
- count: 0,
151
- inc: 'Incremento',
152
- dec: 'Decremento',
153
- increment() {
154
- this.count++
155
- },
156
- decrement() {
157
- this.count--
158
- },
159
- }
160
-
161
- jsweb.ui.createScope('body', { scope })
162
- </script>
163
- </head>
164
- <body>
165
- <div ui:scope="scope">
166
- <h1>JS Web UI</h1>
167
- <p>Contador: <span ui:text="count"></span></p>
168
- <button ui:text="inc" @click="increment()"></button>
169
- <button ui:text="dec" @click="decrement()"></button>
170
- </div>
171
- </body>
172
- </html>
173
- ```
174
-
175
- ### TypeScript / ESM
176
-
177
- ```typescript
178
- import { createScope, reactive, watch } from '@jsweb/ui'
179
-
180
- const scope = reactive({
181
- count: 0,
182
- inc: 'Incremento',
183
- dec: 'Decremento',
184
- increment() {
185
- this.count++
186
- },
187
- decrement() {
188
- this.count--
189
- },
190
- })
191
-
192
- // Observa mudanças com suporte a oldValue/newValue e disparo imediato opcional
193
- const unwatch = watch(
194
- () => scope.count,
195
- (newVal, oldVal) => {
196
- console.log(`Contador mudou de ${oldVal} para ${newVal}`)
197
- },
198
- { immediate: true },
199
- )
200
-
201
- createScope('#container', { scope })
202
- ```
203
-
204
- ## API JavaScript / TypeScript
205
-
206
- ### `createScope(selectorOrElement, context?)`
207
-
208
- Inicializa e amarra a reatividade ao elemento DOM ou seletor especificado.
209
-
210
- - **`selectorOrElement`**: Seletor CSS (ex: `'#app'`, `'body'`) ou instância de `HTMLElement`.
211
- - **`context`**: Objeto inicial de contexto/estado compartilhado (opcional). Injeta automaticamente o helper `$emit` no escopo.
212
-
213
- ### `reactive(target)`
214
-
215
- Envolve um objeto ou array em um `Proxy` de reatividade de grão fino (_fine-grained_).
216
-
217
- - Suporta reatividade profunda (_deep reactivity_).
218
- - Intercepta mutações em arrays (`push`, `pop`, `splice`, etc.) e mutações de propriedades em objetos.
219
-
220
- ### `watch(source, callback, options?)`
221
-
222
- Observa alterações reativas e executa uma função de callback quando o valor mudar.
223
-
224
- - **`source`**: Objeto reativo completo ou função getter que retorna o valor a ser observado (ex: `() => state.count`).
225
- - **`callback`**: `(newValue: any, oldValue: any) => void`.
226
- - **`options`**: `{ immediate?: boolean }` para acionar a callback imediatamente na primeira execução.
227
- - **Retorno**: Função de cancelamento `stop()` que encerra a observação e limpa dependências.
package/dist/index.es.js DELETED
@@ -1,2 +0,0 @@
1
- var e=null,t=/* @__PURE__ */new WeakMap,n=/* @__PURE__ */new WeakMap,o=/* @__PURE__ */new WeakMap,s=class{fn;active=!0;deps=/* @__PURE__ */new Set;constructor(e){this.fn=e}run(){if(!this.active)return this.fn();this.cleanup(),e=Symbol(),o.set(e,this);try{return this.fn()}finally{o.delete(e),e=null}}stop(){this.active&&(this.cleanup(),this.active=!1)}cleanup(){this.deps.forEach(e=>e.delete(this)),this.deps.clear()}effect(){return{run:()=>this.run(),stop:()=>this.stop()}}};function i(e){const t=new s(e);return t.run(),t.effect()}function r(e,n){const o=t.get(e);if(!o)return;const s=o.get(n);s&&new Set(s).forEach(e=>e.run())}function c(s){if("object"!=typeof s||null===s)return s;if(s instanceof Map||s instanceof Set||s instanceof WeakMap||s instanceof WeakSet||s instanceof Date||s instanceof RegExp||"function"==typeof Node&&s instanceof Node)return s;if(Object.hasOwn(s,"_isReactive"))return s;const i=n.get(s);if(i)return i;const f=new Proxy(s,{get(n,s,i){if("_isReactive"===s)return!0;!function(n,s){if(e){let i=t.get(n);i||(i=/* @__PURE__ */new Map,t.set(n,i));let r=i.get(s);r||(r=/* @__PURE__ */new Set,i.set(s,r));const c=o.get(e);c&&(r.add(c),c.deps.add(r))}}(n,s);const r=Reflect.get(n,s,i);return"object"==typeof r&&null!==r?c(r):r},set(e,t,n,o){const s=Array.isArray(e),i=Reflect.get(e,t,o),c=s&&String(Number(t))===t?Number(t)<e.length:Object.hasOwn(e,t),f=Reflect.set(e,t,n,o);return c?i!==n&&r(e,t):(r(e,t),s&&"length"!==t&&r(e,"length")),f}});return n.set(s,f),f}function f(e,t=/* @__PURE__ */new Set){if("object"!=typeof e||null===e||t.has(e))return e;t.add(e);for(const n in e)f(e[n],t);return e}function u(e,t,n){let o,s=!0;const r=e instanceof Function?e:()=>f(e);return i(()=>{const e=r();s?(s=!1,o=e,n?.immediate&&t(e,void 0)):(t(e,o),o=e)}).stop}function a(e,t={}){try{return new Function(`with(this) { return ${e} }`).call(t)}catch{return}}function l(e,t,n={}){try{const o=t.trim(),s=/^[a-zA-Z_$][0-9a-zA-Z_$.]*$/.test(o);new Function("$event",`with(this) { ${s?`${o} instanceof Function ? ${o}.call(this, $event) : ${o}`:o} }`).call(n,e)}catch{console.warn(`[jsweb/ui] Error evaluating event: ${t}`)}}function d(e){const t=e;t._effects&&(t._effects.forEach(e=>e()),t._effects=[]);const n=Array.from(e.childNodes);for(const o of n)d(o)}function p(e,t={}){const n=e._isReactive?e:c(e);return new Proxy(n,{get:(e,n)=>"_isContext"===n||(n in e?Reflect.get(e,n,e):n in t?Reflect.get(t,n,t):Reflect.get(e,n,e)),set:(e,n,o)=>n in e?Reflect.set(e,n,o,e):n in t?Reflect.set(t,n,o,t):Reflect.set(e,n,o,e),has:(e,n)=>n in e||n in t})}function h(e,t){if(e.nodeType!==Node.ELEMENT_NODE)return;const n=e,o=function(e,t){const n=["ui:scope",":scope"],o=b(e,n);if(!o)return t;const s=a(o,t);if(!s)return;y(e,n),s.$emit||(s.$emit=(t,n)=>{e.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0}))});s.$refs||(s.$refs=t.$refs??/* @__PURE__ */new Map);return p(s,t)}(n,t);if(!o)return;const s=["ui:for",":for"],i=b(n,s);if(i)return y(n,s),void function(e,t,n){if(!e.parentNode)return;const o=/^\s*(.+)\s+(?:in|of)\s+(.+)\s*$/.exec(t);if(!o)return console.warn(`[jsweb/ui] Invalid ui:for expression: ${t}`);const[,s,i]=o,r=["ui:key",":key"],f=b(e,r);y(e,r);const u=crypto.randomUUID(),l=document.createComment(` ui:for ${u} `);e.replaceWith(l);let m=[];v(l,()=>{const t=a(i,n);if(!Array.isArray(t))return m.forEach(e=>{e.el.remove(),d(e.el)}),void(m=[]);const o=[],r=/* @__PURE__ */new Map;m.forEach(e=>r.set(e.key,e)),t.forEach((t,i)=>{let u=i;if(f){const e=p({[s]:t,$index:i},n);u=a(f,e)}const l={[s]:t,$index:i,$key:u};let d=r.get(u);if(d)d.scope[s]=t,d.scope.$index=i,d.scope.$key=u,r.delete(u);else{const t=e.cloneNode(!0),o=c(l);h(t,p(o,n)),d={key:u,el:t,scope:o}}o.push(d)}),r.forEach(e=>{e.el.remove(),d(e.el)});let u=l.nextSibling;o.forEach(e=>{u===e.el?u=u.nextSibling:l.parentNode?.insertBefore(e.el,u)}),m=o})}(n,i,o);const r=["ui:if",":if"],f=b(n,r);f&&(y(n,r),function(e,t,n){if(!e.parentNode)return;const o=crypto.randomUUID(),s=document.createComment(` ui:if ${o} `);e.before(s),v(s,()=>{a(t,n)?e.parentNode||s.parentNode?.insertBefore(e,s.nextSibling):e.parentNode&&e.remove()})}(n,f,o)),function(e,t){const n=Array.from(e.attributes);for(const o of n){const{name:n,value:s}=o,i=["ui:text",":text"].includes(n),r=["ui:bind",":bind"].includes(n),c=["ui:class",":class"].includes(n),f=["ui:style",":style"].includes(n),u=["ui:ref",":ref"].includes(n),a=n.startsWith("ui:")||n.startsWith(":"),l=n.startsWith("ui@")||n.startsWith("@");i?(w(e,s,t),e.removeAttribute(n)):r?($(e,s,t),e.removeAttribute(n)):c?(A(e,s,t),e.removeAttribute(n)):f?(S(e,s,t),e.removeAttribute(n)):u?(g(e,s,t),e.removeAttribute(n)):a?(E(e,n.split(":").pop(),s,t),e.removeAttribute(n)):l&&(x(e,n,s,t),e.removeAttribute(n))}}(n,o);const u=Array.from(n.childNodes);for(const c of u)h(c,o)}function m(e,t={}){const n="string"==typeof e?document.querySelector(e):e;n?(t.$emit||(t.$emit=(e,t)=>{n.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}),t.$refs||(t.$refs=/* @__PURE__ */new Map),h(n,t)):console.warn("[jsweb/ui] Element not found:",e)}function v(e,t){const n=i(t),o=e;o._effects??=[],o._effects.push(n.stop)}function b(e,t){for(const n of t){const t=e.getAttribute(n);if(null!==t)return t}return null}function y(e,t){for(const n of t)e.removeAttribute(n)}function g(e,t,n){const o=t.trim().replace(/^['"]|['"]$/g,"");if(!o)return;const s=n.$refs;if(!s)return;const i=n.$key;if(void 0!==i){let t=s.get(o);t instanceof Map||(t=/* @__PURE__ */new Map,s.set(o,t)),t.set(i,e)}else s.set(o,e);const r=e;r._effects??=[],r._effects.push(()=>{if(void 0!==i){const e=s.get(o);e instanceof Map&&(e.delete(i),0===e.size&&s.delete(o))}else s.get(o)===e&&s.delete(o)})}function w(e,t,n){v(e,()=>{const o=a(t,n);e.textContent=null!=o?String(o):""})}function $(e,t,n){const o=e instanceof HTMLInputElement&&"checkbox"===e.type,s=e instanceof HTMLInputElement&&"radio"===e.type;v(e,()=>{const i=a(t,n);if(o)e.checked=!!i;else if(s)e.checked=e.value===String(i);else{e.value=null==i?"":String(i)}});const i=o||s||e instanceof HTMLSelectElement?"change":"input";e.addEventListener(i,e=>{l(e,`${t} = ${"$event.target."+(o?"checked":"value")}`,n)})}function E(e,t,n,o){v(e,()=>{const s=a(n,o);null==s||!1===s?e.removeAttribute(t):!0===s?e.setAttribute(t,""):e.setAttribute(t,String(s))})}function A(e,t,n){let o=/* @__PURE__ */new Set;v(e,()=>{const s=a(t,n),i=/* @__PURE__ */new Set,r=e=>e&&i.add(e),c=e=>e.split(/\s+/).forEach(r);"string"==typeof s?c(s):Array.isArray(s)?s.flat().forEach(e=>{"string"==typeof e&&c(e)}):"object"==typeof s&&null!==s&&Object.entries(s).forEach(([e,t])=>{t&&c(e)}),o.forEach(t=>{i.has(t)||e.classList.remove(t)}),i.forEach(t=>{o.has(t)||e.classList.add(t)}),o=i})}function S(e,t,n){let o={};v(e,()=>{const s=a(t,n),i="object"==typeof s&&null!==s?s:{};for(const t in o)t in i||(e.style[t]="");for(const t in i)o[t]!==i[t]&&(e.style[t]=i[t]);o={...i}})}function x(e,t,n,o){const[s,...i]=t.split("@").pop().split("."),r=i.includes("outside"),c=r?document:e,f=t=>{if(!e.isConnected)return;const s=t.target instanceof Node;r&&s&&e.contains(t.target)||i.includes("self")&&t.target!==e||(i.includes("prevent")&&t.preventDefault(),i.includes("stop")&&t.stopPropagation(),l(t,n,o))};if(c.addEventListener(s,f),r){const t=e;t._effects??=[],t._effects.push(()=>c.removeEventListener(s,f))}}if("undefined"!=typeof window){const e=window;e.jsweb=e.jsweb||{},e.jsweb.ui={createScope:m,reactive:c,watch:u}}export{m as createScope,c as reactive,u as watch};
2
- //# sourceMappingURL=index.es.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.es.js","names":[],"sources":["../src/reactivity.ts","../src/evaluator.ts","../src/parser.ts","../src/index.ts"],"sourcesContent":["let activeEffect: symbol | null = null\nconst targetMap = new WeakMap<\n object,\n Map<string | symbol, Set<ReactiveEffect>>\n>()\nconst proxyMap = new WeakMap<object, any>()\nconst effectMap = new WeakMap<symbol, ReactiveEffect>()\n\nexport class ReactiveEffect {\n active = true\n deps: Set<Set<ReactiveEffect>> = new Set()\n\n constructor(public fn: () => void) {}\n\n run() {\n if (!this.active) return this.fn()\n\n this.cleanup()\n\n activeEffect = Symbol()\n effectMap.set(activeEffect, this)\n\n try {\n return this.fn()\n } finally {\n effectMap.delete(activeEffect)\n activeEffect = null\n }\n }\n\n stop() {\n if (this.active) {\n this.cleanup()\n this.active = false\n }\n }\n\n cleanup() {\n this.deps.forEach((dep) => dep.delete(this))\n this.deps.clear()\n }\n\n effect() {\n return {\n run: () => this.run(),\n stop: () => this.stop(),\n }\n }\n}\n\nexport function effect(fn: () => void) {\n const ref = new ReactiveEffect(fn)\n ref.run()\n return ref.effect()\n}\n\nexport function track(target: object, key: string | symbol) {\n if (activeEffect) {\n let depsMap = targetMap.get(target)\n if (!depsMap) {\n depsMap = new Map()\n targetMap.set(target, depsMap)\n }\n\n let dep = depsMap.get(key)\n if (!dep) {\n dep = new Set()\n depsMap.set(key, dep)\n }\n\n const active = effectMap.get(activeEffect)\n if (active) {\n dep.add(active)\n active.deps.add(dep)\n }\n }\n}\n\nexport function trigger(target: object, key: string | symbol) {\n const depsMap = targetMap.get(target)\n if (!depsMap) return\n\n const dep = depsMap.get(key)\n if (dep) {\n const effects = new Set(dep)\n effects.forEach((effect) => effect.run())\n }\n}\n\nexport function reactive<T extends object>(target: T): T {\n const notObject = typeof target !== 'object' || target === null\n if (notObject) return target\n\n if (\n target instanceof Map ||\n target instanceof Set ||\n target instanceof WeakMap ||\n target instanceof WeakSet ||\n target instanceof Date ||\n target instanceof RegExp ||\n (typeof Node === 'function' && target instanceof Node)\n ) {\n return target\n }\n\n const isReactive = Object.hasOwn(target, '_isReactive')\n if (isReactive) return target\n\n const existingProxy = proxyMap.get(target)\n if (existingProxy) return existingProxy\n\n const proxy = new Proxy(target, {\n get(obj, key, receiver) {\n if (key === '_isReactive') return true\n track(obj, key)\n\n const res = Reflect.get(obj, key, receiver)\n // deep reactivity\n return typeof res === 'object' && res !== null ? reactive(res) : res\n },\n set(obj, key, value, receiver) {\n const isArray = Array.isArray(obj)\n const oldValue = Reflect.get(obj, key, receiver)\n const hadKey =\n isArray && String(Number(key)) === key\n ? Number(key) < obj.length\n : Object.hasOwn(obj, key)\n\n const result = Reflect.set(obj, key, value, receiver)\n\n if (!hadKey) {\n trigger(obj, key)\n if (isArray && key !== 'length') {\n trigger(obj, 'length')\n }\n } else if (oldValue !== value) {\n trigger(obj, key)\n }\n\n return result\n },\n })\n\n proxyMap.set(target, proxy)\n return proxy\n}\n\nexport function traverse(value: any, seen = new Set()) {\n if (typeof value !== 'object' || value === null || seen.has(value)) {\n return value\n }\n seen.add(value)\n for (const key in value) {\n traverse(value[key], seen)\n }\n return value\n}\n\nexport function watch(\n source: any | (() => any),\n cb: (newValue: any, oldValue: any) => void,\n options?: { immediate?: boolean },\n) {\n let oldValue: any\n let isFirstRun = true\n\n const getter = source instanceof Function ? source : () => traverse(source)\n\n const runner = effect(() => {\n const newValue = getter()\n\n if (isFirstRun) {\n isFirstRun = false\n oldValue = newValue\n if (options?.immediate) {\n cb(newValue, undefined)\n }\n } else {\n cb(newValue, oldValue)\n oldValue = newValue\n }\n })\n\n return runner.stop\n}\n","export function evaluate(\n expression: string,\n context: Record<string, any> = {},\n) {\n try {\n const fn = new Function(`with(this) { return ${expression} }`)\n return fn.call(context)\n } catch {\n return undefined\n }\n}\n\nexport function evaluateEvent(\n $event: Event,\n expression: string,\n context: Record<string, any> = {},\n) {\n try {\n const exp = expression.trim()\n const isIdentifier = /^[a-zA-Z_$][0-9a-zA-Z_$.]*$/.test(exp)\n const code = `${exp} instanceof Function ? ${exp}.call(this, $event) : ${exp}`\n const result = isIdentifier ? code : exp\n const fn = new Function('$event', `with(this) { ${result} }`)\n\n fn.call(context, $event)\n } catch {\n console.warn(`[jsweb/ui] Error evaluating event: ${expression}`)\n }\n}\n","import { effect, reactive } from './reactivity'\nimport { evaluate, evaluateEvent } from './evaluator'\n\nexport type Context = Record<string, any>\n\ninterface BoundNode extends Node {\n _effects?: Array<() => void>\n}\n\nexport function cleanupTree(node: Node) {\n const bNode = node as BoundNode\n if (bNode._effects) {\n bNode._effects.forEach((stop) => stop())\n bNode._effects = []\n }\n const children = Array.from(node.childNodes)\n for (const child of children) cleanupTree(child)\n}\n\nexport function createContext(scope: any, context: Context = {}): Context {\n const reactiveScope = scope._isReactive ? scope : reactive(scope)\n\n return new Proxy(reactiveScope, {\n get(target, prop) {\n if (prop === '_isContext') return true\n if (prop in target) return Reflect.get(target, prop, target)\n if (prop in context) {\n return Reflect.get(context, prop, context)\n }\n return Reflect.get(target, prop, target)\n },\n set(target, prop, value) {\n if (prop in target) return Reflect.set(target, prop, value, target)\n if (prop in context) {\n return Reflect.set(context, prop, value, context)\n }\n return Reflect.set(target, prop, value, target)\n },\n has(target, prop) {\n if (prop in target) return true\n if (prop in context) return true\n return false\n },\n })\n}\n\nexport function parseNode(node: Node, context: Context) {\n if (node.nodeType !== Node.ELEMENT_NODE) return\n\n const el = node as HTMLElement\n const scope = processScope(el, context)\n if (!scope) return\n\n const forAttrs = ['ui:for', ':for']\n const forDirective = getDirectiveValue(el, forAttrs)\n if (forDirective) {\n removeDirectiveAttributes(el, forAttrs)\n processFor(el, forDirective, scope)\n return\n }\n\n const ifAttrs = ['ui:if', ':if']\n const ifDirective = getDirectiveValue(el, ifAttrs)\n if (ifDirective) {\n removeDirectiveAttributes(el, ifAttrs)\n processIf(el, ifDirective, scope)\n }\n\n processAttributes(el, scope)\n\n const children = Array.from(el.childNodes)\n for (const child of children) parseNode(child, scope)\n}\n\nexport function createScope(\n selectorOrElement: string | HTMLElement,\n context: Context = {},\n) {\n const el =\n typeof selectorOrElement === 'string'\n ? document.querySelector(selectorOrElement)\n : selectorOrElement\n\n if (el) {\n if (!context.$emit) {\n context.$emit = (eventName: string, detail?: any) => {\n el.dispatchEvent(\n new CustomEvent(eventName, { detail, bubbles: true, composed: true }),\n )\n }\n }\n\n if (!context.$refs) {\n context.$refs = new Map<string, any>()\n }\n\n parseNode(el, context)\n } else {\n console.warn('[jsweb/ui] Element not found:', selectorOrElement)\n }\n}\n\nfunction bindEffect(node: Node, fn: () => void) {\n const e = effect(fn)\n const bNode = node as BoundNode\n bNode._effects ??= []\n bNode._effects.push(e.stop)\n}\n\nfunction getDirectiveValue(el: HTMLElement, names: string[]) {\n for (const name of names) {\n const value = el.getAttribute(name)\n if (value !== null) return value\n }\n return null\n}\n\nfunction removeDirectiveAttributes(el: HTMLElement, names: string[]) {\n for (const name of names) {\n el.removeAttribute(name)\n }\n}\n\nfunction processScope(el: HTMLElement, context: Context) {\n const attrs = ['ui:scope', ':scope']\n const directive = getDirectiveValue(el, attrs)\n if (!directive) return context\n\n const scope = evaluate(directive, context)\n if (!scope) return undefined\n\n removeDirectiveAttributes(el, attrs)\n\n if (!scope.$emit) {\n scope.$emit = (event: string, detail?: any) => {\n el.dispatchEvent(\n new CustomEvent(event, { detail, bubbles: true, composed: true }),\n )\n }\n }\n\n if (!scope.$refs) {\n scope.$refs = context.$refs ?? new Map<string, any>()\n }\n\n return createContext(scope, context)\n}\n\nfunction processFor(el: HTMLElement, expr: string, context: Context) {\n const parent = el.parentNode\n if (!parent) return\n\n const match = /^\\s*(.+)\\s+(?:in|of)\\s+(.+)\\s*$/.exec(expr)\n if (!match) {\n return console.warn(`[jsweb/ui] Invalid ui:for expression: ${expr}`)\n }\n const [, itemName, listName] = match\n\n const keyAttr = ['ui:key', ':key']\n const keyDirective = getDirectiveValue(el, keyAttr)\n removeDirectiveAttributes(el, keyAttr)\n\n const uuid = crypto.randomUUID()\n const comment = document.createComment(` ui:for ${uuid} `)\n el.replaceWith(comment)\n\n interface RenderedNode {\n key: any\n el: HTMLElement\n scope: any\n }\n let renderedNodes: RenderedNode[] = []\n\n bindEffect(comment, () => {\n const list = evaluate(listName, context)\n\n if (!Array.isArray(list)) {\n renderedNodes.forEach((node) => {\n node.el.remove()\n cleanupTree(node.el)\n })\n renderedNodes = []\n return\n }\n\n const newNodes: RenderedNode[] = []\n const oldNodesByKey = new Map<any, RenderedNode>()\n renderedNodes.forEach((node) => oldNodesByKey.set(node.key, node))\n\n list.forEach((item, index) => {\n let key: any = index\n\n if (keyDirective) {\n const tempContext = createContext(\n { [itemName]: item, $index: index },\n context,\n )\n key = evaluate(keyDirective, tempContext)\n }\n\n const scope = { [itemName]: item, $index: index, $key: key }\n\n let node = oldNodesByKey.get(key)\n if (node) {\n // Reuse node\n node.scope[itemName] = item\n node.scope.$index = index\n node.scope.$key = key\n oldNodesByKey.delete(key)\n } else {\n // Create new node\n const clone = el.cloneNode(true) as HTMLElement\n const reactiveScope = reactive(scope)\n const localContext = createContext(reactiveScope, context)\n parseNode(clone, localContext)\n node = { key, el: clone, scope: reactiveScope }\n }\n\n newNodes.push(node)\n })\n\n // Remove un-reused nodes\n oldNodesByKey.forEach((node) => {\n node.el.remove()\n cleanupTree(node.el)\n })\n\n // Reorder and insert new DOM nodes\n let currentAnchor = comment.nextSibling\n newNodes.forEach((node) => {\n if (currentAnchor === node.el) {\n currentAnchor = currentAnchor.nextSibling\n } else {\n comment.parentNode?.insertBefore(node.el, currentAnchor)\n }\n })\n\n renderedNodes = newNodes\n })\n}\n\nfunction processIf(el: HTMLElement, expr: string, context: Context) {\n const parent = el.parentNode\n if (!parent) return\n\n const uuid = crypto.randomUUID()\n const comment = document.createComment(` ui:if ${uuid} `)\n el.before(comment)\n\n bindEffect(comment, () => {\n const val = evaluate(expr, context)\n if (val) {\n if (!el.parentNode) {\n comment.parentNode?.insertBefore(el, comment.nextSibling)\n }\n } else if (el.parentNode) {\n el.remove()\n }\n })\n}\n\nfunction processAttributes(el: HTMLElement, context: Context) {\n const attrs = Array.from(el.attributes)\n\n for (const attr of attrs) {\n const { name, value } = attr\n const isText = ['ui:text', ':text'].includes(name)\n const isTwoWayBind = ['ui:bind', ':bind'].includes(name)\n const isClassBind = ['ui:class', ':class'].includes(name)\n const isStyleBind = ['ui:style', ':style'].includes(name)\n const isRef = ['ui:ref', ':ref'].includes(name)\n const isAttrBind = name.startsWith('ui:') || name.startsWith(':')\n const isEvent = name.startsWith('ui@') || name.startsWith('@')\n\n if (isText) {\n processTextBinding(el, value, context)\n el.removeAttribute(name)\n } else if (isTwoWayBind) {\n processTwoWayBinding(el, value, context)\n el.removeAttribute(name)\n } else if (isClassBind) {\n processClassBinding(el, value, context)\n el.removeAttribute(name)\n } else if (isStyleBind) {\n processStyleBinding(el, value, context)\n el.removeAttribute(name)\n } else if (isRef) {\n processRef(el, value, context)\n el.removeAttribute(name)\n } else if (isAttrBind) {\n const bound = name.split(':').pop()!\n processAttrBinding(el, bound, value, context)\n el.removeAttribute(name)\n } else if (isEvent) {\n processEventBinding(el, name, value, context)\n el.removeAttribute(name)\n }\n }\n}\n\nfunction processRef(el: HTMLElement, expr: string, context: Context) {\n const refName = expr.trim().replace(/^['\"]|['\"]$/g, '')\n if (!refName) return\n\n const refs = context.$refs as Map<string, any>\n if (!refs) return\n\n const key = context.$key\n\n if (key !== undefined) {\n let group = refs.get(refName)\n if (!(group instanceof Map)) {\n group = new Map<any, HTMLElement>()\n refs.set(refName, group)\n }\n group.set(key, el)\n } else {\n refs.set(refName, el)\n }\n\n const bNode = el as BoundNode\n bNode._effects ??= []\n bNode._effects.push(() => {\n if (key !== undefined) {\n const group = refs.get(refName)\n if (group instanceof Map) {\n group.delete(key)\n if (group.size === 0) {\n refs.delete(refName)\n }\n }\n } else if (refs.get(refName) === el) {\n refs.delete(refName)\n }\n })\n}\n\nfunction processTextBinding(el: HTMLElement, expr: string, context: Context) {\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n el.textContent = val !== undefined && val !== null ? String(val) : ''\n })\n}\n\nfunction processTwoWayBinding(el: HTMLElement, expr: string, context: Context) {\n const isCheckbox = el instanceof HTMLInputElement && el.type === 'checkbox'\n const isRadio = el instanceof HTMLInputElement && el.type === 'radio'\n\n // 1. Reactive state to DOM\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n if (isCheckbox) {\n el.checked = !!val\n } else if (isRadio) {\n el.checked = el.value === String(val)\n } else {\n const target = el as\n | HTMLInputElement\n | HTMLSelectElement\n | HTMLTextAreaElement\n target.value = val == null ? '' : String(val)\n }\n })\n\n // 2. DOM to Reactive state\n const isChange = isCheckbox || isRadio || el instanceof HTMLSelectElement\n const eventName = isChange ? 'change' : 'input'\n el.addEventListener(eventName, ($event) => {\n const target = isCheckbox ? 'checked' : 'value'\n const value = `$event.target.${target}`\n evaluateEvent($event, `${expr} = ${value}`, context)\n })\n}\n\nfunction processAttrBinding(\n el: HTMLElement,\n attr: string,\n expr: string,\n context: Context,\n) {\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n if (val === null || val === undefined || val === false) {\n el.removeAttribute(attr)\n } else if (val === true) {\n el.setAttribute(attr, '')\n } else {\n el.setAttribute(attr, String(val))\n }\n })\n}\n\nfunction processClassBinding(el: HTMLElement, expr: string, context: Context) {\n let oldClasses = new Set<string>()\n\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n const newClasses = new Set<string>()\n const addClass = (c: string) => c && newClasses.add(c)\n const addClasses = (c: string) => c.split(/\\s+/).forEach(addClass)\n\n if (typeof val === 'string') addClasses(val)\n else if (Array.isArray(val)) {\n val.flat().forEach((c: any) => {\n if (typeof c === 'string') addClasses(c)\n })\n } else if (typeof val === 'object' && val !== null) {\n Object.entries(val).forEach(([c, condition]: [string, any]) => {\n if (condition) addClasses(c)\n })\n }\n\n oldClasses.forEach((c) => {\n if (!newClasses.has(c)) el.classList.remove(c)\n })\n newClasses.forEach((c) => {\n if (!oldClasses.has(c)) el.classList.add(c)\n })\n\n oldClasses = newClasses\n })\n}\n\nfunction processStyleBinding(el: HTMLElement, expr: string, context: Context) {\n let oldStyles: Record<string, any> = {}\n\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n const newStyles = typeof val === 'object' && val !== null ? val : {}\n\n for (const key in oldStyles) {\n if (!(key in newStyles)) {\n ;(el.style as any)[key] = ''\n }\n }\n\n for (const key in newStyles) {\n if (oldStyles[key] !== newStyles[key]) {\n ;(el.style as any)[key] = newStyles[key]\n }\n }\n\n oldStyles = { ...newStyles }\n })\n}\n\nfunction processEventBinding(\n el: HTMLElement,\n evt: string,\n expr: string,\n context: Context,\n) {\n const refs = evt.split('@').pop()!\n const [name, ...modifiers] = refs.split('.')\n\n const isOutside = modifiers.includes('outside')\n const target = isOutside ? document : el\n\n const handler: EventListener = ($event: Event) => {\n if (!el.isConnected) return\n\n const isTargetNode = $event.target instanceof Node\n\n if (isOutside && isTargetNode && el.contains($event.target)) return\n if (modifiers.includes('self') && $event.target !== el) return\n\n if (modifiers.includes('prevent')) $event.preventDefault()\n if (modifiers.includes('stop')) $event.stopPropagation()\n\n evaluateEvent($event, expr, context)\n }\n\n target.addEventListener(name, handler)\n\n if (isOutside) {\n const bNode = el as BoundNode\n bNode._effects ??= []\n bNode._effects.push(() => target.removeEventListener(name, handler))\n }\n}\n","import { reactive, watch } from './reactivity'\nimport { createScope } from './parser'\n\nexport { reactive, watch, createScope }\n\nif (typeof window !== 'undefined') {\n const w = window as any\n w.jsweb = w.jsweb || {}\n w.jsweb.ui = { createScope, reactive, watch }\n}\n"],"mappings":"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"}
package/dist/index.umd.js DELETED
@@ -1,2 +0,0 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self)["@jsweb/ui"]={})}(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:"Module"});var t=null,n=new WeakMap,o=new WeakMap,i=new WeakMap,s=class{fn;active=!0;deps=new Set;constructor(e){this.fn=e}run(){if(!this.active)return this.fn();this.cleanup(),t=Symbol(),i.set(t,this);try{return this.fn()}finally{i.delete(t),t=null}}stop(){this.active&&(this.cleanup(),this.active=!1)}cleanup(){this.deps.forEach(e=>e.delete(this)),this.deps.clear()}effect(){return{run:()=>this.run(),stop:()=>this.stop()}}};function c(e){const t=new s(e);return t.run(),t.effect()}function r(e,t){const o=n.get(e);if(!o)return;const i=o.get(t);i&&new Set(i).forEach(e=>e.run())}function f(e){if("object"!=typeof e||null===e)return e;if(e instanceof Map||e instanceof Set||e instanceof WeakMap||e instanceof WeakSet||e instanceof Date||e instanceof RegExp||"function"==typeof Node&&e instanceof Node)return e;if(Object.hasOwn(e,"_isReactive"))return e;const s=o.get(e);if(s)return s;const c=new Proxy(e,{get(e,o,s){if("_isReactive"===o)return!0;!function(e,o){if(t){let s=n.get(e);s||(s=new Map,n.set(e,s));let c=s.get(o);c||(c=new Set,s.set(o,c));const r=i.get(t);r&&(c.add(r),r.deps.add(c))}}(e,o);const c=Reflect.get(e,o,s);return"object"==typeof c&&null!==c?f(c):c},set(e,t,n,o){const i=Array.isArray(e),s=Reflect.get(e,t,o),c=i&&String(Number(t))===t?Number(t)<e.length:Object.hasOwn(e,t),f=Reflect.set(e,t,n,o);return c?s!==n&&r(e,t):(r(e,t),i&&"length"!==t&&r(e,"length")),f}});return o.set(e,c),c}function u(e,t=new Set){if("object"!=typeof e||null===e||t.has(e))return e;t.add(e);for(const n in e)u(e[n],t);return e}function a(e,t,n){let o,i=!0;const s=e instanceof Function?e:()=>u(e);return c(()=>{const e=s();i?(i=!1,o=e,n?.immediate&&t(e,void 0)):(t(e,o),o=e)}).stop}function l(e,t={}){try{return new Function(`with(this) { return ${e} }`).call(t)}catch{return}}function d(e,t,n={}){try{const o=t.trim(),i=/^[a-zA-Z_$][0-9a-zA-Z_$.]*$/.test(o);new Function("$event",`with(this) { ${i?`${o} instanceof Function ? ${o}.call(this, $event) : ${o}`:o} }`).call(n,e)}catch{console.warn(`[jsweb/ui] Error evaluating event: ${t}`)}}function p(e){const t=e;t._effects&&(t._effects.forEach(e=>e()),t._effects=[]);const n=Array.from(e.childNodes);for(const o of n)p(o)}function h(e,t={}){const n=e._isReactive?e:f(e);return new Proxy(n,{get:(e,n)=>"_isContext"===n||(n in e?Reflect.get(e,n,e):n in t?Reflect.get(t,n,t):Reflect.get(e,n,e)),set:(e,n,o)=>n in e?Reflect.set(e,n,o,e):n in t?Reflect.set(t,n,o,t):Reflect.set(e,n,o,e),has:(e,n)=>n in e||n in t})}function m(e,t){if(e.nodeType!==Node.ELEMENT_NODE)return;const n=e,o=function(e,t){const n=["ui:scope",":scope"],o=y(e,n);if(!o)return t;const i=l(o,t);if(!i)return;g(e,n),i.$emit||(i.$emit=(t,n)=>{e.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0}))});i.$refs||(i.$refs=t.$refs??new Map);return h(i,t)}(n,t);if(!o)return;const i=["ui:for",":for"],s=y(n,i);if(s)return g(n,i),void function(e,t,n){if(!e.parentNode)return;const o=/^\s*(.+)\s+(?:in|of)\s+(.+)\s*$/.exec(t);if(!o)return console.warn(`[jsweb/ui] Invalid ui:for expression: ${t}`);const[,i,s]=o,c=["ui:key",":key"],r=y(e,c);g(e,c);const u=crypto.randomUUID(),a=document.createComment(` ui:for ${u} `);e.replaceWith(a);let d=[];v(a,()=>{const t=l(s,n);if(!Array.isArray(t))return d.forEach(e=>{e.el.remove(),p(e.el)}),void(d=[]);const o=[],c=new Map;d.forEach(e=>c.set(e.key,e)),t.forEach((t,s)=>{let u=s;if(r){const e=h({[i]:t,$index:s},n);u=l(r,e)}const a={[i]:t,$index:s,$key:u};let d=c.get(u);if(d)d.scope[i]=t,d.scope.$index=s,d.scope.$key=u,c.delete(u);else{const t=e.cloneNode(!0),o=f(a);m(t,h(o,n)),d={key:u,el:t,scope:o}}o.push(d)}),c.forEach(e=>{e.el.remove(),p(e.el)});let u=a.nextSibling;o.forEach(e=>{u===e.el?u=u.nextSibling:a.parentNode?.insertBefore(e.el,u)}),d=o})}(n,s,o);const c=["ui:if",":if"],r=y(n,c);r&&(g(n,c),function(e,t,n){if(!e.parentNode)return;const o=crypto.randomUUID(),i=document.createComment(` ui:if ${o} `);e.before(i),v(i,()=>{l(t,n)?e.parentNode||i.parentNode?.insertBefore(e,i.nextSibling):e.parentNode&&e.remove()})}(n,r,o)),function(e,t){const n=Array.from(e.attributes);for(const o of n){const{name:n,value:i}=o,s=["ui:text",":text"].includes(n),c=["ui:bind",":bind"].includes(n),r=["ui:class",":class"].includes(n),f=["ui:style",":style"].includes(n),u=["ui:ref",":ref"].includes(n),a=n.startsWith("ui:")||n.startsWith(":"),l=n.startsWith("ui@")||n.startsWith("@");s?($(e,i,t),e.removeAttribute(n)):c?(E(e,i,t),e.removeAttribute(n)):r?(S(e,i,t),e.removeAttribute(n)):f?(x(e,i,t),e.removeAttribute(n)):u?(w(e,i,t),e.removeAttribute(n)):a?(A(e,n.split(":").pop(),i,t),e.removeAttribute(n)):l&&(j(e,n,i,t),e.removeAttribute(n))}}(n,o);const u=Array.from(n.childNodes);for(const f of u)m(f,o)}function b(e,t={}){const n="string"==typeof e?document.querySelector(e):e;n?(t.$emit||(t.$emit=(e,t)=>{n.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}),t.$refs||(t.$refs=new Map),m(n,t)):console.warn("[jsweb/ui] Element not found:",e)}function v(e,t){const n=c(t),o=e;o._effects??=[],o._effects.push(n.stop)}function y(e,t){for(const n of t){const t=e.getAttribute(n);if(null!==t)return t}return null}function g(e,t){for(const n of t)e.removeAttribute(n)}function w(e,t,n){const o=t.trim().replace(/^['"]|['"]$/g,"");if(!o)return;const i=n.$refs;if(!i)return;const s=n.$key;if(void 0!==s){let t=i.get(o);t instanceof Map||(t=new Map,i.set(o,t)),t.set(s,e)}else i.set(o,e);const c=e;c._effects??=[],c._effects.push(()=>{if(void 0!==s){const e=i.get(o);e instanceof Map&&(e.delete(s),0===e.size&&i.delete(o))}else i.get(o)===e&&i.delete(o)})}function $(e,t,n){v(e,()=>{const o=l(t,n);e.textContent=null!=o?String(o):""})}function E(e,t,n){const o=e instanceof HTMLInputElement&&"checkbox"===e.type,i=e instanceof HTMLInputElement&&"radio"===e.type;v(e,()=>{const s=l(t,n);if(o)e.checked=!!s;else if(i)e.checked=e.value===String(s);else{e.value=null==s?"":String(s)}});const s=o||i||e instanceof HTMLSelectElement?"change":"input";e.addEventListener(s,e=>{d(e,`${t} = ${"$event.target."+(o?"checked":"value")}`,n)})}function A(e,t,n,o){v(e,()=>{const i=l(n,o);null==i||!1===i?e.removeAttribute(t):!0===i?e.setAttribute(t,""):e.setAttribute(t,String(i))})}function S(e,t,n){let o=new Set;v(e,()=>{const i=l(t,n),s=new Set,c=e=>e&&s.add(e),r=e=>e.split(/\s+/).forEach(c);"string"==typeof i?r(i):Array.isArray(i)?i.flat().forEach(e=>{"string"==typeof e&&r(e)}):"object"==typeof i&&null!==i&&Object.entries(i).forEach(([e,t])=>{t&&r(e)}),o.forEach(t=>{s.has(t)||e.classList.remove(t)}),s.forEach(t=>{o.has(t)||e.classList.add(t)}),o=s})}function x(e,t,n){let o={};v(e,()=>{const i=l(t,n),s="object"==typeof i&&null!==i?i:{};for(const t in o)t in s||(e.style[t]="");for(const t in s)o[t]!==s[t]&&(e.style[t]=s[t]);o={...s}})}function j(e,t,n,o){const[i,...s]=t.split("@").pop().split("."),c=s.includes("outside"),r=c?document:e,f=t=>{if(!e.isConnected)return;const i=t.target instanceof Node;c&&i&&e.contains(t.target)||s.includes("self")&&t.target!==e||(s.includes("prevent")&&t.preventDefault(),s.includes("stop")&&t.stopPropagation(),d(t,n,o))};if(r.addEventListener(i,f),c){const t=e;t._effects??=[],t._effects.push(()=>r.removeEventListener(i,f))}}if("undefined"!=typeof window){const e=window;e.jsweb=e.jsweb||{},e.jsweb.ui={createScope:b,reactive:f,watch:a}}e.createScope=b,e.reactive=f,e.watch=a});
2
- //# sourceMappingURL=index.umd.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.umd.js","names":[],"sources":["../src/reactivity.ts","../src/evaluator.ts","../src/parser.ts","../src/index.ts"],"sourcesContent":["let activeEffect: symbol | null = null\nconst targetMap = new WeakMap<\n object,\n Map<string | symbol, Set<ReactiveEffect>>\n>()\nconst proxyMap = new WeakMap<object, any>()\nconst effectMap = new WeakMap<symbol, ReactiveEffect>()\n\nexport class ReactiveEffect {\n active = true\n deps: Set<Set<ReactiveEffect>> = new Set()\n\n constructor(public fn: () => void) {}\n\n run() {\n if (!this.active) return this.fn()\n\n this.cleanup()\n\n activeEffect = Symbol()\n effectMap.set(activeEffect, this)\n\n try {\n return this.fn()\n } finally {\n effectMap.delete(activeEffect)\n activeEffect = null\n }\n }\n\n stop() {\n if (this.active) {\n this.cleanup()\n this.active = false\n }\n }\n\n cleanup() {\n this.deps.forEach((dep) => dep.delete(this))\n this.deps.clear()\n }\n\n effect() {\n return {\n run: () => this.run(),\n stop: () => this.stop(),\n }\n }\n}\n\nexport function effect(fn: () => void) {\n const ref = new ReactiveEffect(fn)\n ref.run()\n return ref.effect()\n}\n\nexport function track(target: object, key: string | symbol) {\n if (activeEffect) {\n let depsMap = targetMap.get(target)\n if (!depsMap) {\n depsMap = new Map()\n targetMap.set(target, depsMap)\n }\n\n let dep = depsMap.get(key)\n if (!dep) {\n dep = new Set()\n depsMap.set(key, dep)\n }\n\n const active = effectMap.get(activeEffect)\n if (active) {\n dep.add(active)\n active.deps.add(dep)\n }\n }\n}\n\nexport function trigger(target: object, key: string | symbol) {\n const depsMap = targetMap.get(target)\n if (!depsMap) return\n\n const dep = depsMap.get(key)\n if (dep) {\n const effects = new Set(dep)\n effects.forEach((effect) => effect.run())\n }\n}\n\nexport function reactive<T extends object>(target: T): T {\n const notObject = typeof target !== 'object' || target === null\n if (notObject) return target\n\n if (\n target instanceof Map ||\n target instanceof Set ||\n target instanceof WeakMap ||\n target instanceof WeakSet ||\n target instanceof Date ||\n target instanceof RegExp ||\n (typeof Node === 'function' && target instanceof Node)\n ) {\n return target\n }\n\n const isReactive = Object.hasOwn(target, '_isReactive')\n if (isReactive) return target\n\n const existingProxy = proxyMap.get(target)\n if (existingProxy) return existingProxy\n\n const proxy = new Proxy(target, {\n get(obj, key, receiver) {\n if (key === '_isReactive') return true\n track(obj, key)\n\n const res = Reflect.get(obj, key, receiver)\n // deep reactivity\n return typeof res === 'object' && res !== null ? reactive(res) : res\n },\n set(obj, key, value, receiver) {\n const isArray = Array.isArray(obj)\n const oldValue = Reflect.get(obj, key, receiver)\n const hadKey =\n isArray && String(Number(key)) === key\n ? Number(key) < obj.length\n : Object.hasOwn(obj, key)\n\n const result = Reflect.set(obj, key, value, receiver)\n\n if (!hadKey) {\n trigger(obj, key)\n if (isArray && key !== 'length') {\n trigger(obj, 'length')\n }\n } else if (oldValue !== value) {\n trigger(obj, key)\n }\n\n return result\n },\n })\n\n proxyMap.set(target, proxy)\n return proxy\n}\n\nexport function traverse(value: any, seen = new Set()) {\n if (typeof value !== 'object' || value === null || seen.has(value)) {\n return value\n }\n seen.add(value)\n for (const key in value) {\n traverse(value[key], seen)\n }\n return value\n}\n\nexport function watch(\n source: any | (() => any),\n cb: (newValue: any, oldValue: any) => void,\n options?: { immediate?: boolean },\n) {\n let oldValue: any\n let isFirstRun = true\n\n const getter = source instanceof Function ? source : () => traverse(source)\n\n const runner = effect(() => {\n const newValue = getter()\n\n if (isFirstRun) {\n isFirstRun = false\n oldValue = newValue\n if (options?.immediate) {\n cb(newValue, undefined)\n }\n } else {\n cb(newValue, oldValue)\n oldValue = newValue\n }\n })\n\n return runner.stop\n}\n","export function evaluate(\n expression: string,\n context: Record<string, any> = {},\n) {\n try {\n const fn = new Function(`with(this) { return ${expression} }`)\n return fn.call(context)\n } catch {\n return undefined\n }\n}\n\nexport function evaluateEvent(\n $event: Event,\n expression: string,\n context: Record<string, any> = {},\n) {\n try {\n const exp = expression.trim()\n const isIdentifier = /^[a-zA-Z_$][0-9a-zA-Z_$.]*$/.test(exp)\n const code = `${exp} instanceof Function ? ${exp}.call(this, $event) : ${exp}`\n const result = isIdentifier ? code : exp\n const fn = new Function('$event', `with(this) { ${result} }`)\n\n fn.call(context, $event)\n } catch {\n console.warn(`[jsweb/ui] Error evaluating event: ${expression}`)\n }\n}\n","import { effect, reactive } from './reactivity'\nimport { evaluate, evaluateEvent } from './evaluator'\n\nexport type Context = Record<string, any>\n\ninterface BoundNode extends Node {\n _effects?: Array<() => void>\n}\n\nexport function cleanupTree(node: Node) {\n const bNode = node as BoundNode\n if (bNode._effects) {\n bNode._effects.forEach((stop) => stop())\n bNode._effects = []\n }\n const children = Array.from(node.childNodes)\n for (const child of children) cleanupTree(child)\n}\n\nexport function createContext(scope: any, context: Context = {}): Context {\n const reactiveScope = scope._isReactive ? scope : reactive(scope)\n\n return new Proxy(reactiveScope, {\n get(target, prop) {\n if (prop === '_isContext') return true\n if (prop in target) return Reflect.get(target, prop, target)\n if (prop in context) {\n return Reflect.get(context, prop, context)\n }\n return Reflect.get(target, prop, target)\n },\n set(target, prop, value) {\n if (prop in target) return Reflect.set(target, prop, value, target)\n if (prop in context) {\n return Reflect.set(context, prop, value, context)\n }\n return Reflect.set(target, prop, value, target)\n },\n has(target, prop) {\n if (prop in target) return true\n if (prop in context) return true\n return false\n },\n })\n}\n\nexport function parseNode(node: Node, context: Context) {\n if (node.nodeType !== Node.ELEMENT_NODE) return\n\n const el = node as HTMLElement\n const scope = processScope(el, context)\n if (!scope) return\n\n const forAttrs = ['ui:for', ':for']\n const forDirective = getDirectiveValue(el, forAttrs)\n if (forDirective) {\n removeDirectiveAttributes(el, forAttrs)\n processFor(el, forDirective, scope)\n return\n }\n\n const ifAttrs = ['ui:if', ':if']\n const ifDirective = getDirectiveValue(el, ifAttrs)\n if (ifDirective) {\n removeDirectiveAttributes(el, ifAttrs)\n processIf(el, ifDirective, scope)\n }\n\n processAttributes(el, scope)\n\n const children = Array.from(el.childNodes)\n for (const child of children) parseNode(child, scope)\n}\n\nexport function createScope(\n selectorOrElement: string | HTMLElement,\n context: Context = {},\n) {\n const el =\n typeof selectorOrElement === 'string'\n ? document.querySelector(selectorOrElement)\n : selectorOrElement\n\n if (el) {\n if (!context.$emit) {\n context.$emit = (eventName: string, detail?: any) => {\n el.dispatchEvent(\n new CustomEvent(eventName, { detail, bubbles: true, composed: true }),\n )\n }\n }\n\n if (!context.$refs) {\n context.$refs = new Map<string, any>()\n }\n\n parseNode(el, context)\n } else {\n console.warn('[jsweb/ui] Element not found:', selectorOrElement)\n }\n}\n\nfunction bindEffect(node: Node, fn: () => void) {\n const e = effect(fn)\n const bNode = node as BoundNode\n bNode._effects ??= []\n bNode._effects.push(e.stop)\n}\n\nfunction getDirectiveValue(el: HTMLElement, names: string[]) {\n for (const name of names) {\n const value = el.getAttribute(name)\n if (value !== null) return value\n }\n return null\n}\n\nfunction removeDirectiveAttributes(el: HTMLElement, names: string[]) {\n for (const name of names) {\n el.removeAttribute(name)\n }\n}\n\nfunction processScope(el: HTMLElement, context: Context) {\n const attrs = ['ui:scope', ':scope']\n const directive = getDirectiveValue(el, attrs)\n if (!directive) return context\n\n const scope = evaluate(directive, context)\n if (!scope) return undefined\n\n removeDirectiveAttributes(el, attrs)\n\n if (!scope.$emit) {\n scope.$emit = (event: string, detail?: any) => {\n el.dispatchEvent(\n new CustomEvent(event, { detail, bubbles: true, composed: true }),\n )\n }\n }\n\n if (!scope.$refs) {\n scope.$refs = context.$refs ?? new Map<string, any>()\n }\n\n return createContext(scope, context)\n}\n\nfunction processFor(el: HTMLElement, expr: string, context: Context) {\n const parent = el.parentNode\n if (!parent) return\n\n const match = /^\\s*(.+)\\s+(?:in|of)\\s+(.+)\\s*$/.exec(expr)\n if (!match) {\n return console.warn(`[jsweb/ui] Invalid ui:for expression: ${expr}`)\n }\n const [, itemName, listName] = match\n\n const keyAttr = ['ui:key', ':key']\n const keyDirective = getDirectiveValue(el, keyAttr)\n removeDirectiveAttributes(el, keyAttr)\n\n const uuid = crypto.randomUUID()\n const comment = document.createComment(` ui:for ${uuid} `)\n el.replaceWith(comment)\n\n interface RenderedNode {\n key: any\n el: HTMLElement\n scope: any\n }\n let renderedNodes: RenderedNode[] = []\n\n bindEffect(comment, () => {\n const list = evaluate(listName, context)\n\n if (!Array.isArray(list)) {\n renderedNodes.forEach((node) => {\n node.el.remove()\n cleanupTree(node.el)\n })\n renderedNodes = []\n return\n }\n\n const newNodes: RenderedNode[] = []\n const oldNodesByKey = new Map<any, RenderedNode>()\n renderedNodes.forEach((node) => oldNodesByKey.set(node.key, node))\n\n list.forEach((item, index) => {\n let key: any = index\n\n if (keyDirective) {\n const tempContext = createContext(\n { [itemName]: item, $index: index },\n context,\n )\n key = evaluate(keyDirective, tempContext)\n }\n\n const scope = { [itemName]: item, $index: index, $key: key }\n\n let node = oldNodesByKey.get(key)\n if (node) {\n // Reuse node\n node.scope[itemName] = item\n node.scope.$index = index\n node.scope.$key = key\n oldNodesByKey.delete(key)\n } else {\n // Create new node\n const clone = el.cloneNode(true) as HTMLElement\n const reactiveScope = reactive(scope)\n const localContext = createContext(reactiveScope, context)\n parseNode(clone, localContext)\n node = { key, el: clone, scope: reactiveScope }\n }\n\n newNodes.push(node)\n })\n\n // Remove un-reused nodes\n oldNodesByKey.forEach((node) => {\n node.el.remove()\n cleanupTree(node.el)\n })\n\n // Reorder and insert new DOM nodes\n let currentAnchor = comment.nextSibling\n newNodes.forEach((node) => {\n if (currentAnchor === node.el) {\n currentAnchor = currentAnchor.nextSibling\n } else {\n comment.parentNode?.insertBefore(node.el, currentAnchor)\n }\n })\n\n renderedNodes = newNodes\n })\n}\n\nfunction processIf(el: HTMLElement, expr: string, context: Context) {\n const parent = el.parentNode\n if (!parent) return\n\n const uuid = crypto.randomUUID()\n const comment = document.createComment(` ui:if ${uuid} `)\n el.before(comment)\n\n bindEffect(comment, () => {\n const val = evaluate(expr, context)\n if (val) {\n if (!el.parentNode) {\n comment.parentNode?.insertBefore(el, comment.nextSibling)\n }\n } else if (el.parentNode) {\n el.remove()\n }\n })\n}\n\nfunction processAttributes(el: HTMLElement, context: Context) {\n const attrs = Array.from(el.attributes)\n\n for (const attr of attrs) {\n const { name, value } = attr\n const isText = ['ui:text', ':text'].includes(name)\n const isTwoWayBind = ['ui:bind', ':bind'].includes(name)\n const isClassBind = ['ui:class', ':class'].includes(name)\n const isStyleBind = ['ui:style', ':style'].includes(name)\n const isRef = ['ui:ref', ':ref'].includes(name)\n const isAttrBind = name.startsWith('ui:') || name.startsWith(':')\n const isEvent = name.startsWith('ui@') || name.startsWith('@')\n\n if (isText) {\n processTextBinding(el, value, context)\n el.removeAttribute(name)\n } else if (isTwoWayBind) {\n processTwoWayBinding(el, value, context)\n el.removeAttribute(name)\n } else if (isClassBind) {\n processClassBinding(el, value, context)\n el.removeAttribute(name)\n } else if (isStyleBind) {\n processStyleBinding(el, value, context)\n el.removeAttribute(name)\n } else if (isRef) {\n processRef(el, value, context)\n el.removeAttribute(name)\n } else if (isAttrBind) {\n const bound = name.split(':').pop()!\n processAttrBinding(el, bound, value, context)\n el.removeAttribute(name)\n } else if (isEvent) {\n processEventBinding(el, name, value, context)\n el.removeAttribute(name)\n }\n }\n}\n\nfunction processRef(el: HTMLElement, expr: string, context: Context) {\n const refName = expr.trim().replace(/^['\"]|['\"]$/g, '')\n if (!refName) return\n\n const refs = context.$refs as Map<string, any>\n if (!refs) return\n\n const key = context.$key\n\n if (key !== undefined) {\n let group = refs.get(refName)\n if (!(group instanceof Map)) {\n group = new Map<any, HTMLElement>()\n refs.set(refName, group)\n }\n group.set(key, el)\n } else {\n refs.set(refName, el)\n }\n\n const bNode = el as BoundNode\n bNode._effects ??= []\n bNode._effects.push(() => {\n if (key !== undefined) {\n const group = refs.get(refName)\n if (group instanceof Map) {\n group.delete(key)\n if (group.size === 0) {\n refs.delete(refName)\n }\n }\n } else if (refs.get(refName) === el) {\n refs.delete(refName)\n }\n })\n}\n\nfunction processTextBinding(el: HTMLElement, expr: string, context: Context) {\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n el.textContent = val !== undefined && val !== null ? String(val) : ''\n })\n}\n\nfunction processTwoWayBinding(el: HTMLElement, expr: string, context: Context) {\n const isCheckbox = el instanceof HTMLInputElement && el.type === 'checkbox'\n const isRadio = el instanceof HTMLInputElement && el.type === 'radio'\n\n // 1. Reactive state to DOM\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n if (isCheckbox) {\n el.checked = !!val\n } else if (isRadio) {\n el.checked = el.value === String(val)\n } else {\n const target = el as\n | HTMLInputElement\n | HTMLSelectElement\n | HTMLTextAreaElement\n target.value = val == null ? '' : String(val)\n }\n })\n\n // 2. DOM to Reactive state\n const isChange = isCheckbox || isRadio || el instanceof HTMLSelectElement\n const eventName = isChange ? 'change' : 'input'\n el.addEventListener(eventName, ($event) => {\n const target = isCheckbox ? 'checked' : 'value'\n const value = `$event.target.${target}`\n evaluateEvent($event, `${expr} = ${value}`, context)\n })\n}\n\nfunction processAttrBinding(\n el: HTMLElement,\n attr: string,\n expr: string,\n context: Context,\n) {\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n if (val === null || val === undefined || val === false) {\n el.removeAttribute(attr)\n } else if (val === true) {\n el.setAttribute(attr, '')\n } else {\n el.setAttribute(attr, String(val))\n }\n })\n}\n\nfunction processClassBinding(el: HTMLElement, expr: string, context: Context) {\n let oldClasses = new Set<string>()\n\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n const newClasses = new Set<string>()\n const addClass = (c: string) => c && newClasses.add(c)\n const addClasses = (c: string) => c.split(/\\s+/).forEach(addClass)\n\n if (typeof val === 'string') addClasses(val)\n else if (Array.isArray(val)) {\n val.flat().forEach((c: any) => {\n if (typeof c === 'string') addClasses(c)\n })\n } else if (typeof val === 'object' && val !== null) {\n Object.entries(val).forEach(([c, condition]: [string, any]) => {\n if (condition) addClasses(c)\n })\n }\n\n oldClasses.forEach((c) => {\n if (!newClasses.has(c)) el.classList.remove(c)\n })\n newClasses.forEach((c) => {\n if (!oldClasses.has(c)) el.classList.add(c)\n })\n\n oldClasses = newClasses\n })\n}\n\nfunction processStyleBinding(el: HTMLElement, expr: string, context: Context) {\n let oldStyles: Record<string, any> = {}\n\n bindEffect(el, () => {\n const val = evaluate(expr, context)\n const newStyles = typeof val === 'object' && val !== null ? val : {}\n\n for (const key in oldStyles) {\n if (!(key in newStyles)) {\n ;(el.style as any)[key] = ''\n }\n }\n\n for (const key in newStyles) {\n if (oldStyles[key] !== newStyles[key]) {\n ;(el.style as any)[key] = newStyles[key]\n }\n }\n\n oldStyles = { ...newStyles }\n })\n}\n\nfunction processEventBinding(\n el: HTMLElement,\n evt: string,\n expr: string,\n context: Context,\n) {\n const refs = evt.split('@').pop()!\n const [name, ...modifiers] = refs.split('.')\n\n const isOutside = modifiers.includes('outside')\n const target = isOutside ? document : el\n\n const handler: EventListener = ($event: Event) => {\n if (!el.isConnected) return\n\n const isTargetNode = $event.target instanceof Node\n\n if (isOutside && isTargetNode && el.contains($event.target)) return\n if (modifiers.includes('self') && $event.target !== el) return\n\n if (modifiers.includes('prevent')) $event.preventDefault()\n if (modifiers.includes('stop')) $event.stopPropagation()\n\n evaluateEvent($event, expr, context)\n }\n\n target.addEventListener(name, handler)\n\n if (isOutside) {\n const bNode = el as BoundNode\n bNode._effects ??= []\n bNode._effects.push(() => target.removeEventListener(name, handler))\n }\n}\n","import { reactive, watch } from './reactivity'\nimport { createScope } from './parser'\n\nexport { reactive, watch, createScope }\n\nif (typeof window !== 'undefined') {\n const w = window as any\n w.jsweb = w.jsweb || {}\n w.jsweb.ui = { createScope, reactive, watch }\n}\n"],"mappings":"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"}
package/dist/package.json DELETED
@@ -1,34 +0,0 @@
1
- {
2
- "name": "@jsweb/ui",
3
- "version": "1.2.8",
4
- "description": "JS Web Microframework",
5
- "keywords": [
6
- "js",
7
- "ts",
8
- "web",
9
- "ui",
10
- "micro",
11
- "framework"
12
- ],
13
- "homepage": "https://github.com/jsweb/ui#readme",
14
- "bugs": {
15
- "url": "https://github.com/jsweb/ui/issues"
16
- },
17
- "repository": {
18
- "type": "git",
19
- "url": "git+https://github.com/jsweb/ui.git"
20
- },
21
- "license": "MIT",
22
- "author": "Alex Bruno Cáceres <email@alexbruno.dev>",
23
- "type": "module",
24
- "main": "index.umd.js",
25
- "module": "index.es.js",
26
- "types": "index.d.ts",
27
- "exports": {
28
- ".": {
29
- "import": "./index.es.js",
30
- "require": "./index.umd.js",
31
- "types": "./index.d.ts"
32
- }
33
- }
34
- }
@@ -1,3 +0,0 @@
1
- import { reactive, watch } from './reactivity';
2
- import { createScope } from './parser';
3
- export { reactive, watch, createScope };
@@ -1,24 +0,0 @@
1
- export declare class ReactiveEffect {
2
- fn: () => void;
3
- active: boolean;
4
- deps: Set<Set<ReactiveEffect>>;
5
- constructor(fn: () => void);
6
- run(): void;
7
- stop(): void;
8
- cleanup(): void;
9
- effect(): {
10
- run: () => void;
11
- stop: () => void;
12
- };
13
- }
14
- export declare function effect(fn: () => void): {
15
- run: () => void;
16
- stop: () => void;
17
- };
18
- export declare function track(target: object, key: string | symbol): void;
19
- export declare function trigger(target: object, key: string | symbol): void;
20
- export declare function reactive<T extends object>(target: T): T;
21
- export declare function traverse(value: any, seen?: Set<unknown>): any;
22
- export declare function watch(source: any | (() => any), cb: (newValue: any, oldValue: any) => void, options?: {
23
- immediate?: boolean;
24
- }): () => void;
@@ -1,2 +0,0 @@
1
- declare const _default: import('vite').UserConfig;
2
- export default _default;