sprae 6.1.1 → 6.1.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/package.json +8 -1
- package/readme.md +55 -41
- package/sprae.auto.js +1 -1
- package/sprae.auto.min.js +1 -1
- package/sprae.js +1 -1
- package/sprae.min.js +1 -1
- package/src/core.js +5 -5
- package/src/directives.js +36 -37
- package/.gitattributes +0 -2
- package/.github/workflows/node.js.yml +0 -30
- package/examples/todomvc.html +0 -98
- package/r&d.md +0 -620
- package/test/attrs.js +0 -754
- package/test/events.js +0 -138
- package/test/index.html +0 -36
- package/test/register.cjs +0 -20
- package/test/state.js +0 -296
- package/test/test.js +0 -13
- package/todo.md +0 -54
package/r&d.md
DELETED
|
@@ -1,620 +0,0 @@
|
|
|
1
|
-
## [x] name -> sprae
|
|
2
|
-
|
|
3
|
-
* rasa
|
|
4
|
-
* dew
|
|
5
|
-
* water
|
|
6
|
-
* humidify
|
|
7
|
-
* sprinkle
|
|
8
|
-
* va
|
|
9
|
-
* soma
|
|
10
|
-
* ley
|
|
11
|
-
* ros
|
|
12
|
-
* dewdrops
|
|
13
|
-
* mtn-dew
|
|
14
|
-
* pores
|
|
15
|
-
* drips
|
|
16
|
-
* straw
|
|
17
|
-
* spores
|
|
18
|
-
* spor
|
|
19
|
-
+ spores
|
|
20
|
-
+ russian
|
|
21
|
-
- spor
|
|
22
|
-
+ sport
|
|
23
|
-
* spore
|
|
24
|
-
* sporae
|
|
25
|
-
+ scottish twist
|
|
26
|
-
+ sounds russian-ish too
|
|
27
|
-
- a bit unusual from API perspective...
|
|
28
|
-
+ similar to algae
|
|
29
|
-
+ dots associate with colon prefix
|
|
30
|
-
* spour
|
|
31
|
-
* sprae?
|
|
32
|
-
+ reference to sporae and similar assoication
|
|
33
|
-
+ simpler word
|
|
34
|
-
+ better assoc with hydration
|
|
35
|
-
+ spree
|
|
36
|
-
+ spread
|
|
37
|
-
* sprinkle
|
|
38
|
-
+ better meaning
|
|
39
|
-
- stands out less than sprae
|
|
40
|
-
* aerosol
|
|
41
|
-
* sprea
|
|
42
|
-
+ inherits sprae
|
|
43
|
-
+ prea(ct)
|
|
44
|
-
+ spree and spread
|
|
45
|
-
+ something priya
|
|
46
|
-
+ anagram: parse, spare, spear
|
|
47
|
-
+ river: https://en.wiktionary.org/wiki/Sprea
|
|
48
|
-
+ spring
|
|
49
|
-
- sprae has nice ae ligature
|
|
50
|
-
- sprae is closer to spray
|
|
51
|
-
- sprae is closer to a verb
|
|
52
|
-
|
|
53
|
-
## [x] :attr, :data, :id, :class, :style, :on, :aria - do we enforce JS syntax or support unscoped expression? -> Use JS convention, too many use-cases.
|
|
54
|
-
|
|
55
|
-
1. JS object
|
|
56
|
-
+ JS object can directly set value as `:props="obj"`
|
|
57
|
-
- JS object is a bit verbose `:props="{a:1, b:2}"`, `:on="{click(e){}, touch(e){}}"`
|
|
58
|
-
+ It's very explicitly JS, no confusion must be introduced
|
|
59
|
-
- It makes HTML look a bit more noisy
|
|
60
|
-
+ It is more familiar
|
|
61
|
-
+ JS syntax saves redundant questions and an item from docs
|
|
62
|
-
|
|
63
|
-
2. Custom expressions
|
|
64
|
-
+ We anyways introduce custom-ish expression in `:each="item in items"`
|
|
65
|
-
- Vue introduces simple-ish parsing for that
|
|
66
|
-
+ Custom expressions are shorter: `:attr="a:1, b:2, c:3"`
|
|
67
|
-
- Custom expressions are confusing for style: `:style="a:1, b:2, c:3"` - very similar to direct style string
|
|
68
|
-
|
|
69
|
-
## [x] Attribute directive: `:={a:1}` vs `:attr={a:1}` vs `:prop={a:1}` -> hold on for now
|
|
70
|
-
|
|
71
|
-
+ `:=obj` reminds pascal assignment operator, which is cool
|
|
72
|
-
+ `:={a:1,b:2}` is natural convention from vue/alpine as - all props in object are assigned as `:{attr}`
|
|
73
|
-
- We can use `:="{data}"` fro sprae autoinit, since scope has confusing name: `:scope={}`, `:sprae={}`, `:with={}`
|
|
74
|
-
-> let's use :prop= for now, since `:={}` can have multiple interpretations
|
|
75
|
-
|
|
76
|
-
## [x] Scopes mechanism: prototype inheritance chain vs multiple `with` wrappers -> init subtrees, no need for explicit mechanism
|
|
77
|
-
|
|
78
|
-
- prototype inheritance chain causes deps update difficulties
|
|
79
|
-
- prototype chain is messy-ish
|
|
80
|
-
- prototype chain is a bit more difficult to provide multiple parent scopes
|
|
81
|
-
- prototype state object is inheritance mess - can be super-hard to analyze
|
|
82
|
-
~ `with(a) with(b) with(c)` is the same as `with(a)` with prototype inheritance in terms of access.
|
|
83
|
-
- `with` chain allows runtime update of scopes, eg. child scope was updated to something new.
|
|
84
|
-
- `prototype` chain is fixed from the time of init.
|
|
85
|
-
- `prototype` chain hails to unidentified root scope and inherits from that. Maybe we should clarify scopes inhertiance and first implement reactive store (see next item).
|
|
86
|
-
|
|
87
|
-
? what if we avoid scope inheritance mechanism (what's the real use for it?) and instead just make reactive store object, so that :with directive subscribes to any input props, but "shadows" subtree?
|
|
88
|
-
? are there uses for inheritance
|
|
89
|
-
|
|
90
|
-
? Do we need scopes at all? Only for the purpose of autoinit?
|
|
91
|
-
- it seems scopes can introduce more confusion and mess in templates: indicating full paths is more beneficial
|
|
92
|
-
+ unless we introduce proper ":with="item.x as x""
|
|
93
|
-
+ prototype chain is a single object:
|
|
94
|
-
+ meaning updators receive one actual-for-element scope instance
|
|
95
|
-
+ that makes external API easier
|
|
96
|
-
+ that allows handling store via single reactive object
|
|
97
|
-
|
|
98
|
-
-> possibly we have to just subscribe via mechanism of signals-like deps, and :with just initializes subtree with extended object
|
|
99
|
-
|
|
100
|
-
## [x] :with? -> let's use `:with="{x:1,y:2,z:3}"` for now
|
|
101
|
-
|
|
102
|
-
1. Get rid of :with
|
|
103
|
-
+ with is bad JS practice/association
|
|
104
|
-
+? is there a bona-fide use case?
|
|
105
|
-
+ the implementation is heavy/unoptimal: two assign-updates happen: for root, for children
|
|
106
|
-
+ it is exception blocking streamline implementation of refs
|
|
107
|
-
+ it shadows data which creates all sorts of nasty debugging effects / states. Isn't it better to keep data/state transparent?
|
|
108
|
-
+ it even enables transparency of :each scopes, since they inherit root scope
|
|
109
|
-
+ it's easier to look out for data in one single place (state init), rather than in a bunch of markup locations
|
|
110
|
-
+?! can be replaced with sort of `<x :xyz="xyz=...calc"></x>`, no?
|
|
111
|
-
-> would need wrapping noname scope access
|
|
112
|
-
+ `:with` defines too many concerns:
|
|
113
|
-
* binds root updates -> child updates;
|
|
114
|
-
* binds child updates to root updates (writes);
|
|
115
|
-
* defines local variables
|
|
116
|
-
* aliases root variables
|
|
117
|
-
? is there value in all of these concerns? It seems we need only local variables, isn't it? Is there a chance partial extension can be required?
|
|
118
|
-
- `:with` can provide situational variables that are useful for props precalculation (since these variables can be reactive.)
|
|
119
|
-
* eg. `<span class="preloader" :with="{str: ''}" :init="setTimeout(() => str+='.', 500)" :text="str" />`
|
|
120
|
-
* that plays role of watch that doesn't require to be outside of local component state.
|
|
121
|
-
- `:with` allows local component state not cluttering global state. There's really no way to define local state that doesn't affect global state.
|
|
122
|
-
1.1 Slim `:with="{a,b,c}"` - just initializes vars
|
|
123
|
-
- Doesn't give easy init syntax
|
|
124
|
-
+ Convevtional and not hard to implement
|
|
125
|
-
2. Use `:let="x, y=2"`?
|
|
126
|
-
+ Doesn't pollute scope but instead cleanly declares local variables
|
|
127
|
-
+ Indicates only local initializer, not subscription
|
|
128
|
-
+ Liquid has `assign` tag `{% assign myVar = false %}` - it only initializes variable
|
|
129
|
-
+ Django `with` performs only alias / complex calc access https://docs.djangoproject.com/en/4.1/ref/templates/builtins/#with - it doesn't sync up global state.
|
|
130
|
-
? call it `:define="x, y, z"`?
|
|
131
|
-
-> it seems `:with="x=1, y=2"` works well. `:let` has dissonance with js'y let.
|
|
132
|
-
? how to extend state
|
|
133
|
-
3. `:with.x="1", :with.y="2"`
|
|
134
|
-
+ easier to parse, since init code can be _messy_
|
|
135
|
-
|
|
136
|
-
## [x] Should we inherit values from `init` in `sprae(el, init)`, instead of creating a snapshot of reactive values in `init`? -> nah, nice idea but too little use. Better create signals struct.
|
|
137
|
-
|
|
138
|
-
+ it allows passing any arbitrary scope to initialize from.
|
|
139
|
-
- it can make hard finding reactive sources...
|
|
140
|
-
+ it is sort-of neat pattern: object parent updates its particular state: it can also have observable method making object a store
|
|
141
|
-
-> can be delegated to a separate functionality - init just gets converted to reactive store
|
|
142
|
-
+ it sort-of makes `init` directly a scope (a parent of scope), which is more natural-ish rather than 2 independent entities
|
|
143
|
-
+ can pass both observables and direct state anywhere, eg. init child components from it
|
|
144
|
-
-> worthy of a separate library, signal-struct?
|
|
145
|
-
|
|
146
|
-
## [x] Per-directive initialize vs per-element initialize -> directives can immediately initialize rest on elements
|
|
147
|
-
|
|
148
|
-
+ Per-directive is very simple and trivial approach
|
|
149
|
-
- Per-directive doesn't read attributes order and init directives independently
|
|
150
|
-
~ Practically linear in-order init doesn't make much service either here
|
|
151
|
-
- Per-directive is a bit hard to deal with scopes
|
|
152
|
-
-> gotta benchmark, vs just walker.
|
|
153
|
-
-> seems unavoidable to combine :if within :each, since :each should remove elements and init on find only
|
|
154
|
-
|
|
155
|
-
## [x] avoid updating unchanged directives if values don't affect them -> signal struct
|
|
156
|
-
|
|
157
|
-
? what if we use preact/signals to subscribe only to required props?
|
|
158
|
-
-> parseExpr is going to need to be handled by core.js (not directives), and detect & subscribe to dependencies itself
|
|
159
|
-
-> so that directive updator gets invoked only when any of expr dependencies change
|
|
160
|
-
-> gotta solve via signal-struct
|
|
161
|
-
|
|
162
|
-
## [x] Replace :else-if with :else :if -> not ideal technically, but done
|
|
163
|
-
|
|
164
|
-
+ `:else :if=""` is meaningful expansion of both directives
|
|
165
|
-
+ `:else :if` is coming from JS
|
|
166
|
-
+ `:else :if` doesn't throw error in JSDOM tests
|
|
167
|
-
- less resemblance with vue: who cares, we already remotely resemble it
|
|
168
|
-
|
|
169
|
-
## [x] Keep className marker of directive or not? -> no
|
|
170
|
-
|
|
171
|
-
-> No: first, there's :class directive changing the class itself;
|
|
172
|
-
-> Second, there's easier way to just "evaporate" directive = not initialize twice;
|
|
173
|
-
-> Third, there's too much pollution with class markers
|
|
174
|
-
|
|
175
|
-
## [x] :html? -> Nope: can be implemented via any prop
|
|
176
|
-
|
|
177
|
-
- introduces malign hole of including sprae inside of html
|
|
178
|
-
- nah: can easily be done manually as `:html="this.innerHTML = abc"`. Just need passing context
|
|
179
|
-
|
|
180
|
-
## [x] :fx? -> nah, already works. Just return `null` in any attr, that's it.
|
|
181
|
-
|
|
182
|
-
* let's wait for use-case
|
|
183
|
-
- doesn't necessarily useful, since any directive is already an effect
|
|
184
|
-
+ works already out of box, just creates `fx` attribute if value is returned
|
|
185
|
-
|
|
186
|
-
## [x] :init? -> same as :fx="initCode", but let's have :oninit event.
|
|
187
|
-
|
|
188
|
-
* waiting for use-case
|
|
189
|
-
-> it's better to init element via js than via inline code. Gotta add `:oninit` event.
|
|
190
|
-
|
|
191
|
-
## [x] :key.enter? -> no, can be done manually
|
|
192
|
-
|
|
193
|
-
- opens gateway to generic modifiers
|
|
194
|
-
- introduces a whole mental layer to learn, including combinations of modifiers all around.
|
|
195
|
-
- can be conflicting with event classes.
|
|
196
|
-
- too adhoc-y
|
|
197
|
-
- can be easily done as `:onkeypress="e => e.key === 'Enter'"`
|
|
198
|
-
-> waiting for use-case
|
|
199
|
-
|
|
200
|
-
## [x] :key:boolean="abc" -> nope: can be done manually
|
|
201
|
-
|
|
202
|
-
? do we really need typecast?
|
|
203
|
-
- it can be done manually as `:key="Boolean(abc)"`
|
|
204
|
-
|
|
205
|
-
## [x] `this` in expressions must refer to current element or scope? -> to current element
|
|
206
|
-
|
|
207
|
-
1. `this === element`
|
|
208
|
-
+ Allows this.innerHTML and other customs
|
|
209
|
-
- Can be done easily via `:ref="xxx"`
|
|
210
|
-
+ External handlers don't have access to refs.
|
|
211
|
-
+ Existing convention
|
|
212
|
-
2. `this === scope`
|
|
213
|
-
- scope is not supposed to be extendible
|
|
214
|
-
- scope is already available
|
|
215
|
-
+ methods provided in `init` may not have access to scope _yet_.
|
|
216
|
-
~- not reliable way to obtain scope via `this.x` - better be explicit as `state.x`
|
|
217
|
-
|
|
218
|
-
## [x] :onconnected/:ondisconnected? -> nah, just use noname effect or external functionality eg fast-on-load
|
|
219
|
-
|
|
220
|
-
+ can be useful for :if, :each handlers, eg to start animation when element appears in DOM.
|
|
221
|
-
- it is not connected-disconnected: it has nothing to do with document: it attaches/detaches from parent.
|
|
222
|
-
- connected-disconnected is too long name
|
|
223
|
-
? attach-detach?
|
|
224
|
-
? onmount-onunmount?
|
|
225
|
-
- slows down domdiff
|
|
226
|
-
- can be solved as `<x :if="xxx" :="xxx && (...)'">` automatically
|
|
227
|
-
|
|
228
|
-
## [ ] :onmount/onunmount? ->
|
|
229
|
-
|
|
230
|
-
+ useful for :if, :each
|
|
231
|
-
+ useful to dispose listeners via :onunmount (opposed to hidden symbols)
|
|
232
|
-
- doesn't really solve disposal: if element is attached again, it would need to reattach removed listeners
|
|
233
|
-
-> can be dolved via teardowns returned from updators
|
|
234
|
-
-> nah, event listeners don't need collection, just make sure no refs to element remain
|
|
235
|
-
+ can be useful for lazy-loadings
|
|
236
|
-
|
|
237
|
-
## [x] :focus="direct code", :evt="direct code" -> nah, too messy.
|
|
238
|
-
|
|
239
|
-
+ makes proper use-case for direct code events
|
|
240
|
-
- doesn't make sense for rective properties inside
|
|
241
|
-
+ better fit for special props like `:mount`
|
|
242
|
-
- tons of new special-meaning namespace props
|
|
243
|
-
|
|
244
|
-
## [x] Chain of events: often useful to have shared context. -> Try `:onstart..onend`
|
|
245
|
-
|
|
246
|
-
* focus/blur, connected/disconnected, mousedown/mouseup, keydown/keyup, touchstart/touchmove/touchend, dragstart/dragover/dragend, animationstart/animationover/animationend, transitionstart/transitionend
|
|
247
|
-
? is there a way to organize handlers for chains of events?
|
|
248
|
-
1. :onfocus:onblur="e => e => {}"
|
|
249
|
-
- :onblur looks more like a pseudo
|
|
250
|
-
+ a bit better distinctive visually, less noisy
|
|
251
|
-
- combining root-level attrs them doesn't seem very intuitive for fn waterfall.
|
|
252
|
-
2. :onfocus-blur="e => e => {}"
|
|
253
|
-
- ? is there dash-events? looks like a single event
|
|
254
|
-
- ? why not :on-focus-blur
|
|
255
|
-
- ? why not :onfocus-onblur
|
|
256
|
-
+ can be converted from on="{ focusBlur: event }" via dash notation
|
|
257
|
-
- messy error messages
|
|
258
|
-
+ less :on prefixes
|
|
259
|
-
+ has better "flowy" meaning
|
|
260
|
-
* 2.1 :onfocus-onblur="e => e => {}"
|
|
261
|
-
+ distinctive visually as 1
|
|
262
|
-
+ flowy nature of 2
|
|
263
|
-
- blocks `:onfile-attached` and other dashed events
|
|
264
|
-
- `ona-onb` vs `ona-b-onc` is hard to parse mentally
|
|
265
|
-
3. :onfocus.onblur="e => e => {}"
|
|
266
|
-
- looks like a modifier
|
|
267
|
-
- . can be used as event class onclick.x
|
|
268
|
-
4. `:onfocus--blur="e => e => {}"`
|
|
269
|
-
+ reminds BEM
|
|
270
|
-
- reminds BEM
|
|
271
|
-
5. `:onfocus..blur="e => e => {}"`
|
|
272
|
-
+ reminds range
|
|
273
|
-
+ literally means start..end
|
|
274
|
-
+ all pros of 2.
|
|
275
|
-
+ reminds spray via dots
|
|
276
|
-
- can be confusing if `blur` is event or just property (can that be a property?)
|
|
277
|
-
6. `:onfocus..onblur="e => e => {}"`
|
|
278
|
-
+ all props of 5.
|
|
279
|
-
+ more obvious that blur is event.
|
|
280
|
-
|
|
281
|
-
4. `:onfocus="e => e => {}"` Keep registered pairs of events: just expect focus return blur, etc.
|
|
282
|
-
+ Shorter syntax
|
|
283
|
-
+ Avoids :onfile-attachment-accepted problem
|
|
284
|
-
- Less verbose and explicit
|
|
285
|
-
- No way to customize sequences, eg. custom events
|
|
286
|
-
|
|
287
|
-
## [ ] Plugins
|
|
288
|
-
|
|
289
|
-
* ~~@sprae/tailwind: `<x :tw="mt-1 mx-2"></x>` - separate tailwind utility classes from main ones; allow conditional setters.~~
|
|
290
|
-
* @sprae/item: `<x :item="{type:a, scope:b}"` – provide microdata
|
|
291
|
-
- can be solved naturally, unless there's special meaning
|
|
292
|
-
* @sprae/hcodes: `<x :hcode=""` – provide microformats
|
|
293
|
-
* @sprae/onvisible?
|
|
294
|
-
- can be solved externally
|
|
295
|
-
* @sprae/onintersects
|
|
296
|
-
|
|
297
|
-
## [x] Write any-attributes via `:<prop>? -> yep`
|
|
298
|
-
|
|
299
|
-
+ Since we support attr walking, maybe instead of :on and :prop just allow any attributes?
|
|
300
|
-
+ that would allow event and attr modifiers...
|
|
301
|
-
+ that would allow somewhat alpine/vue-compatible code
|
|
302
|
-
+ makes sense for `:="{}"` spread
|
|
303
|
-
+ makes place for other specific directives `:init=""` etc
|
|
304
|
-
|
|
305
|
-
## [x] :value is confusing: <option> also uses that. -> let's skip for now: onchange is not a big deal
|
|
306
|
-
|
|
307
|
-
? :model="value"
|
|
308
|
-
+ v-model, x-model
|
|
309
|
-
- confusing
|
|
310
|
-
? :in="text"
|
|
311
|
-
? :input="text"
|
|
312
|
-
? :bind="value"
|
|
313
|
-
+ more accurate logically
|
|
314
|
-
- conflicts with existing naming (bind is used for attrs)
|
|
315
|
-
- conflict if used along with `:value="x" :bind="y"`
|
|
316
|
-
-> :value="value" :onchange="e=>value=e.target.value"
|
|
317
|
-
+ more apparent and explicit
|
|
318
|
-
+ less mental load, "model" is too heavy term
|
|
319
|
-
+ overhead is minimal
|
|
320
|
-
+ react-like
|
|
321
|
-
+ it has better control over serialization
|
|
322
|
-
+ `:onchange:oninput="e=>xyz"` is very good
|
|
323
|
-
|
|
324
|
-
## [x] Sandbox? -> we need it anyways via Proxy, so yes
|
|
325
|
-
|
|
326
|
-
1. Use subscript?
|
|
327
|
-
+ solves access to any internal signals on syntactic level
|
|
328
|
-
+ can tentatively be faster than signal-struct
|
|
329
|
-
+ could tentatively get rid of struct and just use signals as input
|
|
330
|
-
~ Yep, it's a bit weird template converts data into some reactive state. Just expose an update method instead and current state like useState hook. This way you can avoid exposing signal-specific functions.
|
|
331
|
-
+ Provides precisely controlled sandbox
|
|
332
|
-
- Some limited lang opportunities
|
|
333
|
-
- need to match many syntax quirks, can be tedious
|
|
334
|
-
~ can be fine to limit expressions to meaningful default: no Proxy, generators, awaits, global access etc.
|
|
335
|
-
- Somewhat heavy to bundle
|
|
336
|
-
~ 1-2kb is not super-heavy, besides kicks out signal-struct (with preact signals?)
|
|
337
|
-
+ Scope is easier to provide: no need for signal proxy
|
|
338
|
-
+ Can detect access errors in advance
|
|
339
|
-
+ Syntax-level access to signals can be inavoidable: external signals still "leak in" (via arrays or etc.).
|
|
340
|
-
+ Updating simple objects should also rerender the template parts, not just signals.
|
|
341
|
-
+ Deps can be analyzed / implemented without signals
|
|
342
|
-
- Screwed up debugging / stacktrace (unless errored properly)
|
|
343
|
-
~+ can actually provide better trace since no internal framework stuff is shown
|
|
344
|
-
+ can let means to enhance subscript's logs
|
|
345
|
-
+ that "unlimits" returned struct, so that any property can be added/deleted.
|
|
346
|
-
- doesn't really save from `new (()=>{}).constructor` hack: we gotta substitute objects too.
|
|
347
|
-
~ Proxy doesn't save from that either
|
|
348
|
-
+ allows easier handle of `:with="a=1,b=2,c=3"` - we just naturally get local variables without messup with global
|
|
349
|
-
+ we can even define locals without `let`...
|
|
350
|
-
- not having "comfy" compatible JS at hand: cognitive load of whole language "layer" in-between
|
|
351
|
-
+ allows `let a = 1; a;` case instead of `let a = 1; return a;`
|
|
352
|
-
- we can't identify dynamic parts like `x[y]`, whereas signals subscribe dynamically
|
|
353
|
-
~ we can detect dynamic parts and handle them on proxy
|
|
354
|
-
+ subscript allows subscriptions to async functions, unlike signals
|
|
355
|
-
|
|
356
|
-
-> We can benchmark if updating set of known dependencies is faster than using preact subscriptions.
|
|
357
|
-
+ it seems more logical min-ground to know in advance what we depend on, rather than detect by-call as signals do.
|
|
358
|
-
+ it's safer not to depend on external tech, considering there's so much competition and changes in reactive land
|
|
359
|
-
~ it indeed takes some reactive-struct, capable of notifying which paths have been changed
|
|
360
|
-
? maybe define setters such that when they're set
|
|
361
|
-
|
|
362
|
-
2. Use sandboxed proxy
|
|
363
|
-
- tougher evaluation
|
|
364
|
-
- no full protection (Function.constructor)
|
|
365
|
-
- relatively slow
|
|
366
|
-
+ does minimal catch
|
|
367
|
-
+ allows scope control
|
|
368
|
-
+ allows dynamic subscription to requested fields ( no need for preact/signals neither for signal-struct )
|
|
369
|
-
+ we anyways need sandbox even in case of subscript
|
|
370
|
-
|
|
371
|
-
## [x] :onclick="direct code" ? -> no: immediately invoked.
|
|
372
|
-
|
|
373
|
-
+ compatible with direct `onclick=...`
|
|
374
|
-
+ no need for arrow/regular functions syntax in templates
|
|
375
|
-
- still need that syntax for filters, maps etc
|
|
376
|
-
+ can be made async by default
|
|
377
|
-
- illicit `event` object
|
|
378
|
-
+ we don't seem to ever need that event argument, many cases are covered by `.prevent` or `.stop`
|
|
379
|
-
~+ generally `e=>` seem to conflict logically with modifiers sense
|
|
380
|
-
+ `e=>` brings syntax burden - we may not ever need functions
|
|
381
|
-
+ less problem detecting `const/let` in code
|
|
382
|
-
- conflicts with regular attrs logic: the code is immediately invoked and can assign a function.
|
|
383
|
-
- `:oninput="e => (handleCaret(e), updateTimecodes())"`
|
|
384
|
-
~ `:oninput="handleCaret(event), updateTimecodes()"`
|
|
385
|
-
- `:onbeforeinput="handleBeforeInput"`
|
|
386
|
-
~ `:onbeforeinput="handleBeforeInput(event)"`
|
|
387
|
-
- `:ondragenter..ondragleave:ondragenter..ondrop="e=>(this.classList.add('w-dragover'),e=>this.classList.remove('w-dragover'))"`
|
|
388
|
-
~ `:ondragenter..ondragleave:ondragenter..ondrop="this.classList.add('w-dragover'), e=>this.classList.remove('w-dragover')"`
|
|
389
|
-
- `:ondrop="e=>console.log(e.dataTransfer.types)||e.preventDefault()"`
|
|
390
|
-
~ `:ondrop.prevent="console.log(event.dataTransfer.types)"`
|
|
391
|
-
- `:onfocus="e => (e.relatedTarget ? e.relatedTarget.focus() : e.target.blur())"`
|
|
392
|
-
~ `:onfocus="event.relatedTarget ? event.relatedTarget.focus() : event.target.blur()"`
|
|
393
|
-
- `:onpopstate.window="e => goto(e.state)"`
|
|
394
|
-
~ `:onpopstate.window="goto(event.state)"`
|
|
395
|
-
- `:onclick.toggle="play"`
|
|
396
|
-
~ `:onclick.toggle="play()"`
|
|
397
|
-
|
|
398
|
-
## [x] Should we introduce `@click` for short-notation events? -> let's keep `:onx` for raw events, `@x` for normal events
|
|
399
|
-
+ gives shorter code for majority of cases
|
|
400
|
-
+ can be non-conflicting
|
|
401
|
-
+ compatible with all frameworks (vue, alpine, lucia, lit)
|
|
402
|
-
+ gives better meaning to modifiers - moves them outside of `:` attribute
|
|
403
|
-
- multiple events `@input@change="code"` is not nice
|
|
404
|
-
~ that's fine and even meaningful
|
|
405
|
-
- chain of events `@focus..@blur="return (e)=>{}"` creates confusing `return` outside of body, as well as inconsistent chain pattern
|
|
406
|
-
? remove that pattern
|
|
407
|
-
+ it's still unsatisfactory: `@mousedown.document..@mouseup.document="e=> (isMouseDown = true, e=> isMouseDown = false)"` works, but what if we want to add `@touchstart..@touchend`, or
|
|
408
|
-
. `@click..@click="play" @keydown.alt-space..@keydown.alt-space="play"`, so in other words we need cross-reaction `@click_or_altspace..@click_or_altspace`, not just one single chain.
|
|
409
|
-
+ actually here `@click@keydown.space..@click@keydown.space` is possible, unlike `:ona..onb` case, the question is how to provide sequence in attribute
|
|
410
|
-
+ the thing is that local state, introduced by initiator events, is not useful by itself, detached from scope.
|
|
411
|
-
. the state is better reflected in data scope, rather than by initiator event.
|
|
412
|
-
? what about temporaries like `@a..@b="id=setTimeout(),()=>clearTimeout(id)"` or `@a.toggle="stop=play(),stop"`
|
|
413
|
-
. use `:with={id:null} @a="id=setTimeout()" @b="clearTimeout(id)"`
|
|
414
|
-
- introduces illicit `event` variable ~ although compatible with standard, still obscure
|
|
415
|
-
- `@` prefix is unchangeable ~ can be removed, not set, but still on the verge.
|
|
416
|
-
- `@click.toggle="code"` has same problem as `@a..@b` - how can we make code separation in attribute?
|
|
417
|
-
+ remove toggle
|
|
418
|
-
+ overall less code
|
|
419
|
-
|
|
420
|
-
## [x] Multiple chain events resolution -> redirect to main event for now
|
|
421
|
-
* Consider
|
|
422
|
-
```
|
|
423
|
-
:onclick..onclick="play"
|
|
424
|
-
:onkeydown.document.alt-space..onkeydown.document.alt-space="play"
|
|
425
|
-
```
|
|
426
|
-
* When started by click and ended by alt-space, it doesn't clear the onclick
|
|
427
|
-
* We actually want here `:onclick:onkeydown.document.alt-space..onclick:onkeydown.document.alt-space`.
|
|
428
|
-
- this makes inconsistency of `..onclick` - colon is missing
|
|
429
|
-
- also it makes precedence of `:` and `..` unclear - what comes before what after.
|
|
430
|
-
|
|
431
|
-
? Can we use `:onclick.toggle="play"`?
|
|
432
|
-
- it doesn't help with switch-over
|
|
433
|
-
? Some 'or' character `:onclick--onkeydown`
|
|
434
|
-
? We can redirect to main event, that's it for now
|
|
435
|
-
|
|
436
|
-
## [x] Should getters convert to computed? -> yes, that's relatively cheap and useful
|
|
437
|
-
|
|
438
|
-
+ shorter and nicer syntax
|
|
439
|
-
- possibly longer init
|
|
440
|
-
|
|
441
|
-
## [ ] Better :ref
|
|
442
|
-
+ :ref="`a-${1}`"
|
|
443
|
-
+ :id:ref="xyz"
|
|
444
|
-
? maybe id should have same signature
|
|
445
|
-
? should it be very similar mechanism to `:with="a=1,b=2"`
|
|
446
|
-
|
|
447
|
-
## [x] Event modifiers :ona.once, `:ona` -> let's try, there's a lot of use for both props and event
|
|
448
|
-
|
|
449
|
-
- .prevent,.stop - not needed since expects a function
|
|
450
|
-
? or should we just trigger it for user?
|
|
451
|
-
? :onclick.outside
|
|
452
|
-
? :onclick.window, :onclick.document
|
|
453
|
-
+ can be needed, eg. mousedown..up can happen outside of current element (stop caret tracking in waveplay)
|
|
454
|
-
? :onclick.once, :onclick.passive, :onclick.capture
|
|
455
|
-
+ can pass props to event listener: there's no other way to do that
|
|
456
|
-
? :onclick.debounce-330
|
|
457
|
-
? :onclick.throttle-750
|
|
458
|
-
+ ...just handy everydayers and saves tons of noise
|
|
459
|
-
? :onclick.self
|
|
460
|
-
~ clicked on self, not the child
|
|
461
|
-
? :onspecial-event.camel, :onx-y.dot
|
|
462
|
-
~
|
|
463
|
-
? :onkeypress.shift.enter, :onmousemove.shift, :onmousemove.alt
|
|
464
|
-
.shift Shift
|
|
465
|
-
.enter Enter
|
|
466
|
-
.space Space
|
|
467
|
-
.ctrl Ctrl
|
|
468
|
-
.cmd Cmd
|
|
469
|
-
.meta Cmd on Mac, Windows key on Windows
|
|
470
|
-
.alt Alt
|
|
471
|
-
.up .down .left .right
|
|
472
|
-
.escape Escape
|
|
473
|
-
.tab Tab
|
|
474
|
-
.caps-lock Caps Lock
|
|
475
|
-
.equal Equal
|
|
476
|
-
.period Period
|
|
477
|
-
.slash Foward Slash
|
|
478
|
-
+ allows separating various key handlers: atm waveplay handles separate keys in the same method `handleKey`
|
|
479
|
-
+ allows tracking mouse interactions with shift hold
|
|
480
|
-
- conflict with dot-separated events
|
|
481
|
-
~not so popular nor encouraged
|
|
482
|
-
- lots of ad-hoc non-standard rules, can be handled in code
|
|
483
|
-
+ allow multiple setters for same props or multiple listeners for same events
|
|
484
|
-
+ oldschool jquery-compatible events
|
|
485
|
-
|
|
486
|
-
* [x] Event modifiers
|
|
487
|
-
* [x] onevt.x, onevt.y
|
|
488
|
-
+ jquery-like
|
|
489
|
-
+ multiple same events
|
|
490
|
-
* [x] onevt.once, onevt.passive, onevt.capture
|
|
491
|
-
+ standard props passing
|
|
492
|
-
* [x] onevt.prevent, onevt.stop
|
|
493
|
-
+ conventional mods
|
|
494
|
-
* [x] onevt.outside onevt.window, onevt.document, onevt.self
|
|
495
|
-
+ useful handlers, conventional mods
|
|
496
|
-
* [x] onevt.throttle-xxx, onevt.debounce-xxx
|
|
497
|
-
+ conventional
|
|
498
|
-
* [x] onevt.shift, onevt.cmd.shift, onevt.meta
|
|
499
|
-
+ conventional
|
|
500
|
-
* [x] onkey.enter, .space, .up|.down|.left|.right, .escape, .tab, .period, .slash, .caps-lock
|
|
501
|
-
+ conventional
|
|
502
|
-
* [x] onkey.nexttick
|
|
503
|
-
+ seems to be needed, but what's the name?
|
|
504
|
-
* onkey.tick, onkey.nexttick, onkey.next,
|
|
505
|
-
* onkey.after, onkey.microtask, onkey.defer, onkey.immediate
|
|
506
|
-
* onkey.tick-1?
|
|
507
|
-
|
|
508
|
-
## [ ] Prop modifiers
|
|
509
|
-
|
|
510
|
-
- overall seems code complication without much benefit
|
|
511
|
-
* [ ] value.bind? value.watch?
|
|
512
|
-
- let's wait for use-case: value can be too big to set it every time
|
|
513
|
-
* [ ] prop.reflect, prop.observe
|
|
514
|
-
- let's wait for use-case
|
|
515
|
-
* [ ] prop.boolean, .number, .string, .array, .object
|
|
516
|
-
- let's wait for use-case
|
|
517
|
-
* [ ] prop.once, prop.fx ? prop.init?
|
|
518
|
-
- doesn't seem required, let's wait for use case
|
|
519
|
-
* [ ] prop.change - run only if value changes
|
|
520
|
-
- seems like unnecessary manual optimization that must be done always automatically
|
|
521
|
-
? are there cases where force-update is necessary?
|
|
522
|
-
* [ ] prop.throttle-xxx, prop.debounce-xxx
|
|
523
|
-
- let's wait until that's really a problem
|
|
524
|
-
* [ ] prop.class
|
|
525
|
-
? what's the use-case
|
|
526
|
-
* [ ] prop.next="" - run update after other DOM updates happen
|
|
527
|
-
* [ ] prop.fx="" - run effect without changing property
|
|
528
|
-
* [ ] x.prop="xyz" - set element property, rather than attribute (following topic)
|
|
529
|
-
* [ ] x.raf="abc" - run regularly?
|
|
530
|
-
* [ ] x.watch-a-b-c - update by change of any of the deps
|
|
531
|
-
* [ ] :x.always - update by _any_ dep change
|
|
532
|
-
* [ ] :class.active="active"
|
|
533
|
-
* [ ] :x.persist="v"
|
|
534
|
-
|
|
535
|
-
## [x] Writing props on elements (like ones in :each) -> nah, just use `:x="this.x=abc"`
|
|
536
|
-
|
|
537
|
-
1. `:x="abc"` creates property + attribute
|
|
538
|
-
- can be excessive pollution
|
|
539
|
-
|
|
540
|
-
2. `.x="abc"`
|
|
541
|
-
~ `:x.x=""` writes both property and attribute...
|
|
542
|
-
- conflicts with class selector
|
|
543
|
-
- blocks dot-separated values
|
|
544
|
-
- breaks convention of reserved namespace via `:`
|
|
545
|
-
|
|
546
|
-
2.1 `_x="abc"`
|
|
547
|
-
- conflicts with `_target="blank"`
|
|
548
|
-
|
|
549
|
-
3. `:.x="abc"`
|
|
550
|
-
+ keeps convention
|
|
551
|
-
+ compatible with `:on*`
|
|
552
|
-
- can be a bit too noisy syntax
|
|
553
|
-
|
|
554
|
-
4. `:_x`
|
|
555
|
-
+ reference to "private"
|
|
556
|
-
- conflicts with `:_target="blank"`
|
|
557
|
-
|
|
558
|
-
5. `:x="this.x=value"`
|
|
559
|
-
+ yepyepyep
|
|
560
|
-
|
|
561
|
-
## [x] Insert content by reusing the node/template -> use `:render="ref" :with="data"`
|
|
562
|
-
|
|
563
|
-
* Makes easy use of repeatable fragments, instead of web-components
|
|
564
|
-
+ sort-of "detached" for-each
|
|
565
|
-
+ reinforces :ref
|
|
566
|
-
? does it replace element or puts a content?
|
|
567
|
-
* Refs:
|
|
568
|
-
* https://github.com/justinfagnani/html-include-element - src=
|
|
569
|
-
* https://www.npmjs.com/package/imported-template - content=path-to-file
|
|
570
|
-
* https://github.com/SirPepe/html-import src="content.selector"
|
|
571
|
-
* https://github.com/Juicy/juicy-html - html="rawhtml"
|
|
572
|
-
* https://www.npmjs.com/package/html-import-wc - src=path
|
|
573
|
-
* https://github.com/sashafirsov/slotted-element - src=path-to-htmlor-json
|
|
574
|
-
* https://github.com/webcomponents/html-imports - href=filepath
|
|
575
|
-
* https://github.com/giuseppeg/xm - import src=filepath
|
|
576
|
-
* https://github.com/ProjectEvergreen/greenwood/tree/master/packages/plugin-include-html#link-tag-html-only
|
|
577
|
-
* https://github.com/maherbo/include-HTML-document-fragment - link href=path
|
|
578
|
-
* https://github.com/github/include-fragment-element - src=path-to-html
|
|
579
|
-
|
|
580
|
-
1. :use="ref-id"
|
|
581
|
-
```
|
|
582
|
-
<template :ref="abc" id="abc"><span :text="abc"></span></template>
|
|
583
|
-
|
|
584
|
-
<div :use="abc" :with="{abc:'def'}"></div>
|
|
585
|
-
<div :use="'#abc'" :with="{abc:'def'}"></div>
|
|
586
|
-
```
|
|
587
|
-
|
|
588
|
-
- `<use>` from SVG replaces element, but we need inserting content
|
|
589
|
-
|
|
590
|
-
2. :content="#template-id"
|
|
591
|
-
|
|
592
|
-
- conflicts with direct inline content
|
|
593
|
-
|
|
594
|
-
3. :include="#template-id"
|
|
595
|
-
|
|
596
|
-
- conflicts with path to file
|
|
597
|
-
|
|
598
|
-
4. :tpl="#template-id"
|
|
599
|
-
|
|
600
|
-
- some confusion of meaning
|
|
601
|
-
|
|
602
|
-
5. :render="#template-id"
|
|
603
|
-
|
|
604
|
-
+ compatible with liquid 5.0
|
|
605
|
-
+ makes sense as :render=a :with=b
|
|
606
|
-
|
|
607
|
-
* Let's think consequently.
|
|
608
|
-
1. `<template>` element has direct purpose for that
|
|
609
|
-
2. We provide content fallback for unloaded elements in case of `:text` as `<x :text="abc">fallback</x>`
|
|
610
|
-
3. There's too many ways to implement fetching - ideally we leave that concern out and focus only on including content
|
|
611
|
-
4. The approach is almost ready declarative custom element. `<template>` is standard part of it - adds to 1.
|
|
612
|
-
|
|
613
|
-
## [x] Remove non-essential directives -> yep, less API friction
|
|
614
|
-
* :aria - can be defined via plain attributes
|
|
615
|
-
* :data - confusable with :scope, doesn't provide much value, can be used as `:data-x=""` etc
|
|
616
|
-
* :={} - what's the meaning? Can be replaced with multiple attributes, no? No: no easy way to spread attributes.
|
|
617
|
-
|
|
618
|
-
## [x] let/const in expressions: allow or prohibit -> let's prohibit, force user to wrap into a function himself
|
|
619
|
-
|
|
620
|
-
- allowing forces wrapping internally, which creates return statement confustion
|