@rip-lang/ui 0.3.65 → 0.3.66

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.
@@ -45,13 +45,24 @@ export Autocomplete = component
45
45
  openMenu: ->
46
46
  open = true
47
47
  @_hlIdx = -1
48
- requestAnimationFrame => @_position()
48
+ @_input?.focus()
49
49
 
50
50
  close: ->
51
51
  open = false
52
52
  @_hlIdx = -1
53
-
54
- _position: -> ARIA.positionBelow @_input, @_list, 2, false
53
+ @_input?.focus()
54
+
55
+ _applyPlacement: ->
56
+ return unless @_list
57
+ *>@_list.style =
58
+ position: 'fixed'
59
+ inset: 'auto'
60
+ margin: '0'
61
+ positionArea: 'bottom start'
62
+ positionTry: 'flip-block, flip-inline, flip-block flip-inline'
63
+ positionVisibility: 'anchors-visible'
64
+ marginTop: '2px'
65
+ minWidth: 'anchor-size(width)'
55
66
 
56
67
  selectIndex: (idx) ->
57
68
  item = filteredItems[idx]
@@ -68,10 +79,7 @@ export Autocomplete = component
68
79
  @value = newVal
69
80
  open = true
70
81
  @_hlIdx = if filteredItems.length > 0 then 0 else -1
71
- setTimeout =>
72
- @_position()
73
- @_updateHighlight()
74
- , 0
82
+ setTimeout (=> @_updateHighlight()), 0
75
83
 
76
84
  onKeydown: (e) ->
77
85
  len = filteredItems.length
@@ -84,7 +92,11 @@ export Autocomplete = component
84
92
  dismiss: => @close()
85
93
  tab: => @close()
86
94
 
87
- ~> ARIA.popupDismiss open, (=> @_list), (=> @close()), [=> @_input], (=> @_position())
95
+ ~>
96
+ if @_list
97
+ @_list.setAttribute 'popover', 'auto'
98
+ @_applyPlacement()
99
+ ARIA.bindPopover open, (=> @_list), ((isOpen) => open = isOpen), (=> @_input)
88
100
 
89
101
  mounted: ->
90
102
  @_hlIdx = -1
@@ -104,10 +116,9 @@ export Autocomplete = component
104
116
  placeholder: @placeholder
105
117
  @input: @onInput
106
118
 
107
- if open and filteredItems.length > 0
108
- div ref: "_list", id: _listId, role: "listbox", $open: true, style: "position:fixed"
109
- for item, idx in filteredItems
110
- div role: "option", tabindex: "-1"
111
- @click: (=> @selectIndex(idx))
112
- @mouseenter: (=> @_hlIdx = idx; @_updateHighlight())
113
- "#{if typeof item is 'string' then item else (item.label or item.name or String(item))}"
119
+ div ref: "_list", id: _listId, role: "listbox", $open: open?!, style: "position:fixed;margin:0;inset:auto"
120
+ for item, idx in filteredItems
121
+ div role: "option", tabindex: "-1"
122
+ @click: (=> @selectIndex(idx))
123
+ @mouseenter: (=> @_hlIdx = idx; @_updateHighlight())
124
+ "#{if typeof item is 'string' then item else (item.label or item.name or String(item))}"
@@ -46,13 +46,23 @@ export Combobox = component
46
46
  openMenu: ->
47
47
  open = true
48
48
  highlightedIndex = -1
49
- requestAnimationFrame => @_position()
49
+ @_input?.focus()
50
50
 
51
51
  close: ->
52
52
  open = false
53
53
  highlightedIndex = -1
54
-
55
- _position: -> ARIA.positionBelow @_input, @_list, 2, false
54
+ @_input?.focus()
55
+
56
+ _applyPlacement: ->
57
+ return unless @_list
58
+ @_list.style.position = 'fixed'
59
+ @_list.style.inset = 'auto'
60
+ @_list.style.margin = '0'
61
+ @_list.style.positionArea = 'bottom start'
62
+ @_list.style.positionTry = 'flip-block, flip-inline, flip-block flip-inline'
63
+ @_list.style.positionVisibility = 'anchors-visible'
64
+ @_list.style.marginTop = '2px'
65
+ @_list.style.minWidth = 'anchor-size(width)'
56
66
 
57
67
  isDisabled: (item) -> item?.hasAttribute?('data-disabled')
58
68
 
@@ -85,7 +95,11 @@ export Combobox = component
85
95
  dismiss: => if open then @close() else @query = ''
86
96
  tab: => @close()
87
97
 
88
- ~> ARIA.popupDismiss open, (=> @_list), (=> @close()), [=> @_content], (=> @_position())
98
+ ~>
99
+ if @_list
100
+ @_list.setAttribute 'popover', 'auto'
101
+ @_applyPlacement()
102
+ ARIA.bindPopover open, (=> @_list), ((isOpen) => open = isOpen), (=> @_input)
89
103
 
90
104
  render
91
105
  . ref: "_content", $open: open?!
@@ -109,17 +123,16 @@ export Combobox = component
109
123
  button aria-label: "Clear", $clear: true, @click: @clear
110
124
  "✕"
111
125
 
112
- # Listbox — conditionally rendered (like Select)
113
- if open and @items.length > 0
114
- div ref: "_list", id: _listId, role: "listbox", $open: true
115
- style: "position:fixed"
116
- for item, idx in @items
117
- div role: "option", tabindex: "-1", id: "#{_listId}-#{idx}"
118
- $value: item
119
- $highlighted: (idx is highlightedIndex)?!
120
- @click: (=> @selectIndex(idx))
121
- @mouseenter: (=> highlightedIndex = idx)
122
- "#{item}"
123
- if open and @items.length is 0 and @query
124
- div role: "status", aria-live: "polite", $empty: true
125
- "No results"
126
+ # Listbox
127
+ div ref: "_list", id: _listId, role: "listbox", style: "position:fixed;margin:0;inset:auto"
128
+ $open: open?!
129
+ for item, idx in @items
130
+ div role: "option", tabindex: "-1", id: "#{_listId}-#{idx}"
131
+ $value: item
132
+ $highlighted: (idx is highlightedIndex)?!
133
+ @click: (=> @selectIndex(idx))
134
+ @mouseenter: (=> highlightedIndex = idx)
135
+ "#{item}"
136
+ if @items.length is 0 and @query
137
+ div role: "status", aria-live: "polite", $empty: true
138
+ "No results"
@@ -17,7 +17,6 @@ export Dialog = component
17
17
  @dismissable := true
18
18
  @initialFocus := null
19
19
 
20
- _prevFocus = null
21
20
  _id =! "dlg-#{Math.random().toString(36).slice(2, 8)}"
22
21
 
23
22
  ~>
@@ -29,7 +28,6 @@ export Dialog = component
29
28
 
30
29
  ~>
31
30
  if @open
32
- _prevFocus = document.activeElement
33
31
  ARIA.lockScroll(this)
34
32
  requestAnimationFrame =>
35
33
  panel = @_dialog
@@ -42,7 +40,6 @@ export Dialog = component
42
40
  panel.querySelectorAll('a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])')?[0]?.focus()
43
41
  return ->
44
42
  ARIA.unlockScroll(this)
45
- _prevFocus?.focus()
46
43
 
47
44
  close: ->
48
45
  @open = false
@@ -66,6 +66,7 @@ export MultiSelect = component
66
66
  open = false
67
67
  query = ''
68
68
  highlightedIndex = -1
69
+ @_input?.focus()
69
70
 
70
71
  onFocusin: -> open = true
71
72
 
@@ -75,7 +76,16 @@ export MultiSelect = component
75
76
  @_close()
76
77
  , 0
77
78
 
78
- _position: -> ARIA.positionBelow @_input, @_list, 2, false
79
+ _applyPlacement: ->
80
+ return unless @_list
81
+ @_list.style.position = 'fixed'
82
+ @_list.style.inset = 'auto'
83
+ @_list.style.margin = '0'
84
+ @_list.style.positionArea = 'bottom start'
85
+ @_list.style.positionTry = 'flip-block, flip-inline, flip-block flip-inline'
86
+ @_list.style.positionVisibility = 'anchors-visible'
87
+ @_list.style.marginTop = '2px'
88
+ @_list.style.minWidth = 'anchor-size(width)'
79
89
 
80
90
  _onKeydown: (e) ->
81
91
  len = filtered.length
@@ -104,8 +114,10 @@ export MultiSelect = component
104
114
  query = ''
105
115
 
106
116
  ~>
107
- if open then requestAnimationFrame => @_position()
108
- ~> ARIA.popupDismiss open, (=> @_list), (=> @_close()), [=> @_content], (=> @_position())
117
+ if @_list
118
+ @_list.setAttribute 'popover', 'auto'
119
+ @_applyPlacement()
120
+ ARIA.bindPopover open, (=> @_list), ((isOpen) => open = isOpen), (=> @_input)
109
121
 
110
122
  render
111
123
  . ref: "_content", $open: open?!, $disabled: @disabled?!
@@ -133,15 +145,17 @@ export MultiSelect = component
133
145
  "✕"
134
146
 
135
147
  # Dropdown
136
- if open and filtered.length > 0
137
- div ref: "_list", id: _listId, role: "listbox", $open: true, aria-multiselectable: "true"
138
- style: "position:fixed"
139
- for item, idx in filtered
140
- div role: "option", tabindex: "-1", id: "#{_listId}-#{idx}"
141
- $value: @_val(item)
142
- $selected: @_isSelected(item)?!
143
- $highlighted: (idx is highlightedIndex)?!
144
- aria-selected: !!@_isSelected(item)
145
- @click: (=> @_toggleItem(item))
146
- @mouseenter: (=> highlightedIndex = idx)
147
- @_label(item)
148
+ div ref: "_list", id: _listId, role: "listbox", $open: open?!, aria-multiselectable: "true"
149
+ style: "position:fixed;margin:0;inset:auto"
150
+ for item, idx in filtered
151
+ div role: "option", tabindex: "-1", id: "#{_listId}-#{idx}"
152
+ $value: @_val(item)
153
+ $selected: @_isSelected(item)?!
154
+ $highlighted: (idx is highlightedIndex)?!
155
+ aria-selected: !!@_isSelected(item)
156
+ @click: (=> @_toggleItem(item))
157
+ @mouseenter: (=> highlightedIndex = idx)
158
+ @_label(item)
159
+ if filtered.length is 0 and query
160
+ div role: "status", aria-live: "polite", $empty: true
161
+ "No results"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rip-lang/ui",
3
- "version": "0.3.65",
3
+ "version": "0.3.66",
4
4
  "author": "Steve Shreeve <steve.shreeve@gmail.com>",
5
5
  "repository": {
6
6
  "type": "git",
@@ -41,11 +41,11 @@
41
41
  "test:e2e:axe": "UI_AXE=1 bunx playwright test -c playwright.config.mjs --project=chromium"
42
42
  },
43
43
  "dependencies": {
44
- "rip-lang": ">=3.13.118"
44
+ "rip-lang": ">=3.13.119"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@axe-core/playwright": "4.11.1",
48
- "@rip-lang/server": "1.3.105",
48
+ "@rip-lang/server": "1.3.108",
49
49
  "playwright": "1.58.2"
50
50
  }
51
51
  }