rip-lang 3.15.4 → 3.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/bin/rip +167 -12
- package/docs/AGENTS.md +1 -1
- package/docs/RIP-APP.md +808 -0
- package/docs/RIP-DUCKDB.md +477 -0
- package/docs/RIP-INTRO.md +396 -0
- package/docs/RIP-LANG.md +59 -5
- package/docs/RIP-SCHEMA.md +191 -8
- package/docs/RIP-TYPES.md +74 -103
- package/docs/demo/README.md +4 -3
- package/docs/dist/rip.js +3627 -1470
- package/docs/dist/rip.min.js +671 -244
- package/docs/dist/rip.min.js.br +0 -0
- package/docs/example/index.json +7 -7
- package/docs/example/index.json.br +0 -0
- package/docs/extensions/duckdb/manifest.json +1 -1
- package/docs/extensions/duckdb/v1.5.2/linux_amd64/ripdb.duckdb_extension.gz +0 -0
- package/docs/extensions/duckdb/v1.5.2/osx_arm64/ripdb.duckdb_extension.gz +0 -0
- package/docs/extensions/vscode/print/index.html +2 -1
- package/docs/extensions/vscode/print/print-1.0.13.vsix +0 -0
- package/docs/extensions/vscode/print/print-1.0.14.vsix +0 -0
- package/docs/extensions/vscode/print/print-latest.vsix +0 -0
- package/docs/extensions/vscode/rip/rip-0.5.15.vsix +0 -0
- package/docs/extensions/vscode/rip/rip-latest.vsix +0 -0
- package/docs/ui/bundle.json +61 -0
- package/docs/ui/bundle.json.br +0 -0
- package/docs/ui/hljs-rip.js +0 -7
- package/docs/ui/index.css +66 -23
- package/docs/ui/index.html +6 -6
- package/package.json +9 -3
- package/rip-loader.js +64 -2
- package/src/AGENTS.md +63 -36
- package/src/browser.js +96 -14
- package/src/compiler.js +960 -143
- package/src/components.js +794 -88
- package/src/{types-emit.js → dts.js} +181 -71
- package/src/grammar/README.md +1 -1
- package/src/grammar/grammar.rip +111 -97
- package/src/lexer.js +132 -18
- package/src/parser.js +203 -205
- package/src/repl.js +74 -6
- package/src/schema/runtime-orm.js +168 -4
- package/src/schema/runtime-validate.js +146 -2
- package/src/schema/runtime.generated.js +314 -6
- package/src/schema/schema.js +5 -5
- package/src/sourcemaps.js +277 -1
- package/src/stdlib.js +253 -0
- package/src/typecheck.js +2023 -106
- package/src/types.js +127 -7
- package/docs/ui/accordion.rip +0 -103
- package/docs/ui/alert-dialog.rip +0 -53
- package/docs/ui/autocomplete.rip +0 -115
- package/docs/ui/avatar.rip +0 -37
- package/docs/ui/badge.rip +0 -15
- package/docs/ui/breadcrumb.rip +0 -47
- package/docs/ui/button-group.rip +0 -26
- package/docs/ui/button.rip +0 -23
- package/docs/ui/card.rip +0 -25
- package/docs/ui/carousel.rip +0 -110
- package/docs/ui/checkbox-group.rip +0 -61
- package/docs/ui/checkbox.rip +0 -33
- package/docs/ui/collapsible.rip +0 -50
- package/docs/ui/combobox.rip +0 -130
- package/docs/ui/context-menu.rip +0 -88
- package/docs/ui/date-picker.rip +0 -206
- package/docs/ui/dialog.rip +0 -60
- package/docs/ui/drawer.rip +0 -58
- package/docs/ui/editable-value.rip +0 -82
- package/docs/ui/field.rip +0 -53
- package/docs/ui/fieldset.rip +0 -22
- package/docs/ui/form.rip +0 -39
- package/docs/ui/grid.rip +0 -901
- package/docs/ui/input-group.rip +0 -28
- package/docs/ui/input.rip +0 -36
- package/docs/ui/label.rip +0 -16
- package/docs/ui/menu.rip +0 -134
- package/docs/ui/menubar.rip +0 -151
- package/docs/ui/meter.rip +0 -36
- package/docs/ui/multi-select.rip +0 -203
- package/docs/ui/native-select.rip +0 -33
- package/docs/ui/nav-menu.rip +0 -126
- package/docs/ui/number-field.rip +0 -162
- package/docs/ui/otp-field.rip +0 -89
- package/docs/ui/pagination.rip +0 -123
- package/docs/ui/popover.rip +0 -93
- package/docs/ui/preview-card.rip +0 -75
- package/docs/ui/progress.rip +0 -25
- package/docs/ui/radio-group.rip +0 -57
- package/docs/ui/resizable.rip +0 -123
- package/docs/ui/scroll-area.rip +0 -145
- package/docs/ui/select.rip +0 -151
- package/docs/ui/separator.rip +0 -17
- package/docs/ui/skeleton.rip +0 -22
- package/docs/ui/slider.rip +0 -165
- package/docs/ui/spinner.rip +0 -17
- package/docs/ui/table.rip +0 -27
- package/docs/ui/tabs.rip +0 -113
- package/docs/ui/textarea.rip +0 -48
- package/docs/ui/toast.rip +0 -87
- package/docs/ui/toggle-group.rip +0 -71
- package/docs/ui/toggle.rip +0 -24
- package/docs/ui/toolbar.rip +0 -38
- package/docs/ui/tooltip.rip +0 -85
- package/src/app.rip +0 -1571
- package/src/sourcemap-merge.js +0 -287
- /package/docs/demo/{components → routes}/_layout.rip +0 -0
- /package/docs/demo/{components → routes}/about.rip +0 -0
- /package/docs/demo/{components → routes}/card.rip +0 -0
- /package/docs/demo/{components → routes}/counter.rip +0 -0
- /package/docs/demo/{components → routes}/index.rip +0 -0
- /package/docs/demo/{components → routes}/todos.rip +0 -0
- /package/src/schema/{dts-emit.js → dts.js} +0 -0
package/docs/ui/dialog.rip
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
# Dialog — accessible headless modal dialog
|
|
2
|
-
#
|
|
3
|
-
# Native `<dialog>` variant that uses `showModal()` for top-layer modality.
|
|
4
|
-
# Restores focus to the previously focused element on close.
|
|
5
|
-
# Auto-wires aria-labelledby (first h1-h6) and aria-describedby (first p).
|
|
6
|
-
#
|
|
7
|
-
# Exposes $open on the backdrop. Ships zero CSS.
|
|
8
|
-
#
|
|
9
|
-
# Usage:
|
|
10
|
-
# Dialog open <=> showDialog, @close: handleClose
|
|
11
|
-
# h2 "Title"
|
|
12
|
-
# p "Content"
|
|
13
|
-
# button @click: (=> showDialog = false), "Close"
|
|
14
|
-
|
|
15
|
-
export Dialog = component
|
|
16
|
-
@open:: boolean := false
|
|
17
|
-
@dismissable:: boolean := true
|
|
18
|
-
@initialFocus:: any := null
|
|
19
|
-
|
|
20
|
-
_id =! "dlg-#{Math.random().toString(36).slice(2, 8)}"
|
|
21
|
-
|
|
22
|
-
~>
|
|
23
|
-
ARIA.bindDialog @open, (=> @_dialog), ((isOpen) =>
|
|
24
|
-
if not isOpen and @open
|
|
25
|
-
@open = false
|
|
26
|
-
@emit 'close'
|
|
27
|
-
), @dismissable
|
|
28
|
-
|
|
29
|
-
~>
|
|
30
|
-
if @open
|
|
31
|
-
ARIA.lockScroll(this)
|
|
32
|
-
requestAnimationFrame =>
|
|
33
|
-
panel = @_dialog
|
|
34
|
-
if panel
|
|
35
|
-
ARIA.wireAria panel, _id
|
|
36
|
-
if @initialFocus
|
|
37
|
-
target = if typeof @initialFocus is 'string' then panel.querySelector(@initialFocus) else @initialFocus
|
|
38
|
-
target?.focus()
|
|
39
|
-
else
|
|
40
|
-
panel.querySelectorAll('a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])')?[0]?.focus()
|
|
41
|
-
return ->
|
|
42
|
-
ARIA.unlockScroll(this)
|
|
43
|
-
|
|
44
|
-
close: ->
|
|
45
|
-
@open = false
|
|
46
|
-
@emit 'close'
|
|
47
|
-
|
|
48
|
-
onKeydown: (e) ->
|
|
49
|
-
if e.key is 'Escape'
|
|
50
|
-
e.preventDefault()
|
|
51
|
-
@close() if @dismissable
|
|
52
|
-
|
|
53
|
-
onBackdropClick: (e) ->
|
|
54
|
-
if e.target is e.currentTarget and @dismissable
|
|
55
|
-
@_dialog?.close()
|
|
56
|
-
|
|
57
|
-
render
|
|
58
|
-
dialog ref: "_dialog", @click: @onBackdropClick, @keydown: @onKeydown
|
|
59
|
-
$open: @open?!
|
|
60
|
-
slot
|
package/docs/ui/drawer.rip
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
# Drawer — accessible headless slide-out panel
|
|
2
|
-
#
|
|
3
|
-
# A Dialog variant that slides from an edge of the screen.
|
|
4
|
-
# Supports dismiss on escape, click-outside, and optional swipe-to-close.
|
|
5
|
-
# Ships zero CSS.
|
|
6
|
-
#
|
|
7
|
-
# Usage:
|
|
8
|
-
# Drawer open <=> showDrawer, side: "right"
|
|
9
|
-
# h2 "Settings"
|
|
10
|
-
# p "Panel content here"
|
|
11
|
-
|
|
12
|
-
export Drawer = component
|
|
13
|
-
@open:: boolean := false
|
|
14
|
-
@side:: "top" | "right" | "bottom" | "left" := "right"
|
|
15
|
-
@dismissable:: boolean := true
|
|
16
|
-
|
|
17
|
-
_prevFocus = null
|
|
18
|
-
_id =! "drw-#{Math.random().toString(36).slice(2, 8)}"
|
|
19
|
-
|
|
20
|
-
~>
|
|
21
|
-
ARIA.bindDialog @open, (=> @_dialog), ((isOpen) =>
|
|
22
|
-
if not isOpen and @open
|
|
23
|
-
@open = false
|
|
24
|
-
@emit 'close'
|
|
25
|
-
), @dismissable
|
|
26
|
-
|
|
27
|
-
~>
|
|
28
|
-
if @open
|
|
29
|
-
_prevFocus = document.activeElement
|
|
30
|
-
ARIA.lockScroll(this)
|
|
31
|
-
requestAnimationFrame =>
|
|
32
|
-
panel = @_dialog
|
|
33
|
-
if panel
|
|
34
|
-
ARIA.wireAria panel, _id
|
|
35
|
-
panel.querySelectorAll('a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])')?[0]?.focus()
|
|
36
|
-
return ->
|
|
37
|
-
ARIA.unlockScroll(this)
|
|
38
|
-
_prevFocus?.focus()
|
|
39
|
-
|
|
40
|
-
close: ->
|
|
41
|
-
@open = false
|
|
42
|
-
@emit 'close'
|
|
43
|
-
|
|
44
|
-
onKeydown: (e) ->
|
|
45
|
-
if e.key is 'Escape' and @dismissable
|
|
46
|
-
e.preventDefault()
|
|
47
|
-
@close()
|
|
48
|
-
|
|
49
|
-
onBackdropClick: (e) ->
|
|
50
|
-
if e.target is e.currentTarget and @dismissable
|
|
51
|
-
@_dialog?.close()
|
|
52
|
-
|
|
53
|
-
render
|
|
54
|
-
dialog ref: "_dialog", $open: @open?!, $side: @side
|
|
55
|
-
@click: @onBackdropClick
|
|
56
|
-
@keydown: @onKeydown
|
|
57
|
-
$side: @side
|
|
58
|
-
slot
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# EditableValue — accessible headless inline editable value
|
|
2
|
-
#
|
|
3
|
-
# Displays a value with an edit trigger. Clicking opens a popover form.
|
|
4
|
-
# Emits 'save' on submit. Ships zero CSS.
|
|
5
|
-
#
|
|
6
|
-
# Usage:
|
|
7
|
-
# EditableValue @save: handleSave
|
|
8
|
-
# span $display: true
|
|
9
|
-
# "John Doe"
|
|
10
|
-
# div $editor: true
|
|
11
|
-
# input type: "text", value: name, @input: (e) => name = e.target.value
|
|
12
|
-
|
|
13
|
-
export EditableValue = component
|
|
14
|
-
@disabled:: boolean := false
|
|
15
|
-
|
|
16
|
-
editing := false
|
|
17
|
-
saving := false
|
|
18
|
-
|
|
19
|
-
_onEdit: ->
|
|
20
|
-
return if @disabled
|
|
21
|
-
editing = true
|
|
22
|
-
requestAnimationFrame => @_position()
|
|
23
|
-
|
|
24
|
-
_onSave: ->
|
|
25
|
-
return if saving
|
|
26
|
-
saving = true
|
|
27
|
-
@emit 'save'
|
|
28
|
-
@close()
|
|
29
|
-
|
|
30
|
-
_onCancel: ->
|
|
31
|
-
editing = false
|
|
32
|
-
saving = false
|
|
33
|
-
|
|
34
|
-
close: ->
|
|
35
|
-
editing = false
|
|
36
|
-
saving = false
|
|
37
|
-
|
|
38
|
-
setSaving: (val) -> saving = val
|
|
39
|
-
|
|
40
|
-
_position: ->
|
|
41
|
-
display = @_root?.querySelector('[data-display]')
|
|
42
|
-
editor = @_root?.querySelector('[data-editor]')
|
|
43
|
-
return unless display and editor
|
|
44
|
-
@_root.style.position = 'relative'
|
|
45
|
-
dr = display.getBoundingClientRect()
|
|
46
|
-
cr = @_root.getBoundingClientRect()
|
|
47
|
-
editor.style.position = 'absolute'
|
|
48
|
-
editor.style.left = "0px"
|
|
49
|
-
editor.style.top = "#{dr.bottom - cr.top + 4}px"
|
|
50
|
-
editor.style.zIndex = '50'
|
|
51
|
-
editor.querySelector('input, textarea, select')?.focus()
|
|
52
|
-
|
|
53
|
-
~>
|
|
54
|
-
_editing = editing # track before any early return
|
|
55
|
-
display = @_root?.querySelector('[data-display]')
|
|
56
|
-
editor = @_root?.querySelector('[data-editor]')
|
|
57
|
-
return unless display and editor
|
|
58
|
-
editor.hidden = not _editing
|
|
59
|
-
if _editing
|
|
60
|
-
editor.setAttribute 'data-open', ''
|
|
61
|
-
onDown = (e) =>
|
|
62
|
-
unless @_root?.contains(e.target)
|
|
63
|
-
@_onCancel()
|
|
64
|
-
document.addEventListener 'mousedown', onDown
|
|
65
|
-
return -> document.removeEventListener 'mousedown', onDown
|
|
66
|
-
else
|
|
67
|
-
editor.removeAttribute 'data-open'
|
|
68
|
-
|
|
69
|
-
onKeydown: (e) ->
|
|
70
|
-
if e.key is 'Escape' and editing
|
|
71
|
-
e.preventDefault()
|
|
72
|
-
@_onCancel()
|
|
73
|
-
if e.key is 'Enter' and editing
|
|
74
|
-
e.preventDefault()
|
|
75
|
-
@_onSave()
|
|
76
|
-
|
|
77
|
-
render
|
|
78
|
-
div ref: "_root", $editing: editing?!, $disabled: @disabled?!, $saving: saving?!
|
|
79
|
-
slot
|
|
80
|
-
unless editing
|
|
81
|
-
button $edit-trigger: true, aria-label: "Edit", @click: @_onEdit
|
|
82
|
-
"✎"
|
package/docs/ui/field.rip
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
# Field — accessible headless form field wrapper
|
|
2
|
-
#
|
|
3
|
-
# Associates a label, description, and error message with a form control.
|
|
4
|
-
# Generates linked IDs for aria-labelledby/describedby/errormessage.
|
|
5
|
-
# Ships zero CSS.
|
|
6
|
-
#
|
|
7
|
-
# Usage:
|
|
8
|
-
# Field label: "Email", error: errors.email
|
|
9
|
-
# Input value <=> email, type: "email"
|
|
10
|
-
|
|
11
|
-
export Field = component
|
|
12
|
-
@label:: string := ""
|
|
13
|
-
@description:: string := ""
|
|
14
|
-
@error:: string := ""
|
|
15
|
-
@disabled:: boolean := false
|
|
16
|
-
@required:: boolean := false
|
|
17
|
-
|
|
18
|
-
_id =! "fld-#{Math.random().toString(36).slice(2, 8)}"
|
|
19
|
-
|
|
20
|
-
mounted: ->
|
|
21
|
-
ctrl = @_root?.querySelector('input, select, textarea, button, [role]')
|
|
22
|
-
if ctrl
|
|
23
|
-
ctrl.setAttribute 'aria-labelledby', "#{_id}-label" if @label
|
|
24
|
-
ctrl.setAttribute 'aria-describedby', "#{_id}-desc" if @description
|
|
25
|
-
ctrl.setAttribute 'aria-errormessage', "#{_id}-err" if @error
|
|
26
|
-
ctrl.setAttribute 'aria-invalid', true if @error
|
|
27
|
-
ctrl.setAttribute 'aria-required', true if @required
|
|
28
|
-
|
|
29
|
-
~>
|
|
30
|
-
ctrl = @_root?.querySelector('input, select, textarea, button, [role]')
|
|
31
|
-
return unless ctrl
|
|
32
|
-
if @error
|
|
33
|
-
ctrl.setAttribute 'aria-invalid', true
|
|
34
|
-
ctrl.setAttribute 'aria-errormessage', "#{_id}-err"
|
|
35
|
-
else
|
|
36
|
-
ctrl.removeAttribute 'aria-invalid'
|
|
37
|
-
ctrl.removeAttribute 'aria-errormessage'
|
|
38
|
-
|
|
39
|
-
render
|
|
40
|
-
div $disabled: @disabled?!, $invalid: @error?!
|
|
41
|
-
if @label
|
|
42
|
-
label id: "#{_id}-label", $label: true
|
|
43
|
-
@label
|
|
44
|
-
if @required
|
|
45
|
-
span $required: true, aria-hidden: "true"
|
|
46
|
-
" *"
|
|
47
|
-
slot
|
|
48
|
-
if @description and not @error
|
|
49
|
-
div id: "#{_id}-desc", $description: true
|
|
50
|
-
@description
|
|
51
|
-
if @error
|
|
52
|
-
div id: "#{_id}-err", role: "alert", $error: true
|
|
53
|
-
@error
|
package/docs/ui/fieldset.rip
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Fieldset — accessible headless fieldset with legend
|
|
2
|
-
#
|
|
3
|
-
# Groups related fields with an optional legend. Disables all children
|
|
4
|
-
# when @disabled is set. Ships zero CSS.
|
|
5
|
-
#
|
|
6
|
-
# Usage:
|
|
7
|
-
# Fieldset legend: "Shipping Address"
|
|
8
|
-
# Field label: "Street"
|
|
9
|
-
# Input value <=> street
|
|
10
|
-
# Field label: "City"
|
|
11
|
-
# Input value <=> city
|
|
12
|
-
|
|
13
|
-
export Fieldset = component
|
|
14
|
-
@legend:: string := ""
|
|
15
|
-
@disabled:: boolean := false
|
|
16
|
-
|
|
17
|
-
render
|
|
18
|
-
fieldset disabled: @disabled, $disabled: @disabled?!
|
|
19
|
-
if @legend
|
|
20
|
-
legend $legend: true
|
|
21
|
-
@legend
|
|
22
|
-
slot
|
package/docs/ui/form.rip
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
# Form — accessible headless form with validation and submission
|
|
2
|
-
#
|
|
3
|
-
# Wraps native <form> with submit handling, validation state, and
|
|
4
|
-
# loading indicator support. Prevents default submission and emits
|
|
5
|
-
# a 'submit' event. Ships zero CSS.
|
|
6
|
-
#
|
|
7
|
-
# Usage:
|
|
8
|
-
# Form @submit: handleSubmit
|
|
9
|
-
# Field label: "Name"
|
|
10
|
-
# Input value <=> name
|
|
11
|
-
# Button
|
|
12
|
-
# "Submit"
|
|
13
|
-
|
|
14
|
-
export Form = component
|
|
15
|
-
@disabled:: boolean := false
|
|
16
|
-
|
|
17
|
-
submitting := false
|
|
18
|
-
submitted := false
|
|
19
|
-
errors := {}
|
|
20
|
-
|
|
21
|
-
_onSubmit: (e) ->
|
|
22
|
-
e.preventDefault()
|
|
23
|
-
return if @disabled or submitting
|
|
24
|
-
submitting = true
|
|
25
|
-
submitted = true
|
|
26
|
-
@emit 'submit', { form: e.target }
|
|
27
|
-
|
|
28
|
-
setErrors: (errs) ->
|
|
29
|
-
errors = errs or {}
|
|
30
|
-
|
|
31
|
-
setSubmitting: (val) ->
|
|
32
|
-
submitting = val
|
|
33
|
-
|
|
34
|
-
render
|
|
35
|
-
form @submit: @_onSubmit, novalidate: true
|
|
36
|
-
$disabled: @disabled?!
|
|
37
|
-
$submitting: submitting?!
|
|
38
|
-
$submitted: submitted?!
|
|
39
|
-
slot
|