sprae 6.1.1 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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