@remix-run/ui 0.1.1 → 0.2.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/README.md +33 -10
- package/dist/animation/animate-layout-mixin.js +66 -66
- package/dist/animation/animate-layout-mixin.js.map +1 -1
- package/dist/animation/spring.d.ts +6 -35
- package/dist/animation/spring.js +9 -8
- package/dist/animation/spring.js.map +1 -1
- package/dist/components/accordion/accordion.d.ts +7 -7
- package/dist/components/accordion/accordion.js +0 -2
- package/dist/components/accordion/accordion.js.map +1 -1
- package/dist/components/accordion/demos/card.demo.d.ts +6 -0
- package/dist/components/accordion/demos/card.demo.js +58 -0
- package/dist/components/accordion/demos/card.demo.js.map +1 -0
- package/dist/components/accordion/demos/multiple.demo.d.ts +6 -0
- package/dist/components/accordion/demos/multiple.demo.js +19 -0
- package/dist/components/accordion/demos/multiple.demo.js.map +1 -0
- package/dist/components/accordion/demos/overview.demo.d.ts +6 -0
- package/dist/components/accordion/demos/overview.demo.js +19 -0
- package/dist/components/accordion/demos/overview.demo.js.map +1 -0
- package/dist/components/breadcrumbs/breadcrumbs.d.ts +1 -1
- package/dist/components/breadcrumbs/breadcrumbs.js +0 -2
- package/dist/components/breadcrumbs/breadcrumbs.js.map +1 -1
- package/dist/components/breadcrumbs/demos/basic.demo.d.ts +5 -0
- package/dist/components/breadcrumbs/demos/basic.demo.js +14 -0
- package/dist/components/breadcrumbs/demos/basic.demo.js.map +1 -0
- package/dist/components/breadcrumbs/demos/separator.demo.d.ts +5 -0
- package/dist/components/breadcrumbs/demos/separator.demo.js +14 -0
- package/dist/components/breadcrumbs/demos/separator.demo.js.map +1 -0
- package/dist/components/button/button.d.ts +86 -4
- package/dist/components/button/button.js +63 -3
- package/dist/components/button/button.js.map +1 -1
- package/dist/components/button/demos/aliases.demo.d.ts +6 -0
- package/dist/components/button/demos/aliases.demo.js +18 -0
- package/dist/components/button/demos/aliases.demo.js.map +1 -0
- package/dist/components/button/demos/basic.demo.d.ts +6 -0
- package/dist/components/button/demos/basic.demo.js +19 -0
- package/dist/components/button/demos/basic.demo.js.map +1 -0
- package/dist/components/button/demos/states.demo.d.ts +6 -0
- package/dist/components/button/demos/states.demo.js +29 -0
- package/dist/components/button/demos/states.demo.js.map +1 -0
- package/dist/components/combobox/combobox.d.ts +11 -11
- package/dist/components/combobox/combobox.js +0 -2
- package/dist/components/combobox/combobox.js.map +1 -1
- package/dist/components/combobox/demos/overview.demo.d.ts +6 -0
- package/dist/components/combobox/demos/overview.demo.js +153 -0
- package/dist/components/combobox/demos/overview.demo.js.map +1 -0
- package/dist/components/listbox/demos/overview.demo.d.ts +6 -0
- package/dist/components/listbox/demos/overview.demo.js +64 -0
- package/dist/components/listbox/demos/overview.demo.js.map +1 -0
- package/dist/components/listbox/listbox.d.ts +4 -9
- package/dist/components/listbox/listbox.js +21 -33
- package/dist/components/listbox/listbox.js.map +1 -1
- package/dist/components/menu/demos/bubbling.demo.d.ts +5 -0
- package/dist/components/menu/demos/bubbling.demo.js +15 -0
- package/dist/components/menu/demos/bubbling.demo.js.map +1 -0
- package/dist/components/menu/demos/overview.demo.d.ts +6 -0
- package/dist/components/menu/demos/overview.demo.js +32 -0
- package/dist/components/menu/demos/overview.demo.js.map +1 -0
- package/dist/components/menu/menu.d.ts +15 -24
- package/dist/components/menu/menu.js +23 -38
- package/dist/components/menu/menu.js.map +1 -1
- package/dist/components/popover/demos/overview.demo.d.ts +6 -0
- package/dist/components/popover/demos/overview.demo.js +64 -0
- package/dist/components/popover/demos/overview.demo.js.map +1 -0
- package/dist/components/popover/popover.d.ts +5 -5
- package/dist/components/popover/popover.js.map +1 -1
- package/dist/components/select/demos/deconstructed.demo.d.ts +6 -0
- package/dist/components/select/demos/deconstructed.demo.js +53 -0
- package/dist/components/select/demos/deconstructed.demo.js.map +1 -0
- package/dist/components/select/demos/overview.demo.d.ts +5 -0
- package/dist/components/select/demos/overview.demo.js +27 -0
- package/dist/components/select/demos/overview.demo.js.map +1 -0
- package/dist/components/select/select.d.ts +11 -11
- package/dist/components/select/select.js +17 -26
- package/dist/components/select/select.js.map +1 -1
- package/dist/components/tabs/tabs.d.ts +6 -6
- package/dist/components/tabs/tabs.js +0 -2
- package/dist/components/tabs/tabs.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js.map +1 -1
- package/dist/interactions/keydown/keydown.d.ts +1 -1
- package/dist/interactions/outside-click/outside-click-mixin.d.ts +2 -1
- package/dist/interactions/typeahead/typeahead-mixin.d.ts +3 -1
- package/dist/runtime/component.d.ts +18 -12
- package/dist/runtime/component.js +93 -80
- package/dist/runtime/component.js.map +1 -1
- package/dist/runtime/core/attributes.d.ts +14 -0
- package/dist/runtime/core/attributes.js +103 -0
- package/dist/runtime/core/attributes.js.map +1 -0
- package/dist/runtime/core/children.d.ts +7 -0
- package/dist/runtime/core/children.js +30 -0
- package/dist/runtime/core/children.js.map +1 -0
- package/dist/runtime/core/props.d.ts +9 -0
- package/dist/runtime/core/props.js +170 -0
- package/dist/runtime/core/props.js.map +1 -0
- package/dist/runtime/core/vnode.d.ts +3 -0
- package/dist/runtime/core/vnode.js +39 -0
- package/dist/runtime/core/vnode.js.map +1 -0
- package/dist/runtime/create-element.js +2 -1
- package/dist/runtime/create-element.js.map +1 -1
- package/dist/runtime/diff-dom.js +47 -14
- package/dist/runtime/diff-dom.js.map +1 -1
- package/dist/runtime/diff-props.d.ts +1 -2
- package/dist/runtime/diff-props.js +2 -181
- package/dist/runtime/diff-props.js.map +1 -1
- package/dist/runtime/dom.d.ts +20 -9
- package/dist/runtime/frame.d.ts +23 -2
- package/dist/runtime/frame.js +41 -47
- package/dist/runtime/frame.js.map +1 -1
- package/dist/runtime/jsx.d.ts +1 -1
- package/dist/runtime/jsx.js +2 -28
- package/dist/runtime/jsx.js.map +1 -1
- package/dist/runtime/mixins/link-mixin.d.ts +5 -1
- package/dist/runtime/mixins/link-mixin.js.map +1 -1
- package/dist/runtime/mixins/mixin.d.ts +2 -1
- package/dist/runtime/mixins/mixin.js +9 -4
- package/dist/runtime/mixins/mixin.js.map +1 -1
- package/dist/runtime/mixins/on-mixin.d.ts +15 -4
- package/dist/runtime/mixins/on-mixin.js +9 -2
- package/dist/runtime/mixins/on-mixin.js.map +1 -1
- package/dist/runtime/mixins/ref-mixin.d.ts +2 -1
- package/dist/runtime/mixins/ref-mixin.js.map +1 -1
- package/dist/runtime/navigation.js +9 -1
- package/dist/runtime/navigation.js.map +1 -1
- package/dist/runtime/reconcile.d.ts +1 -1
- package/dist/runtime/reconcile.js +452 -197
- package/dist/runtime/reconcile.js.map +1 -1
- package/dist/runtime/run.d.ts +17 -2
- package/dist/runtime/run.js.map +1 -1
- package/dist/runtime/scheduler.d.ts +10 -10
- package/dist/runtime/scheduler.js +1 -1
- package/dist/runtime/scheduler.js.map +1 -1
- package/dist/runtime/stream-protocol.d.ts +8 -0
- package/dist/runtime/stream-protocol.js +20 -0
- package/dist/runtime/stream-protocol.js.map +1 -0
- package/dist/runtime/svg-attributes.js +1 -0
- package/dist/runtime/svg-attributes.js.map +1 -1
- package/dist/runtime/to-vnode.js +7 -11
- package/dist/runtime/to-vnode.js.map +1 -1
- package/dist/runtime/vnode.d.ts +11 -5
- package/dist/runtime/vnode.js +6 -3
- package/dist/runtime/vnode.js.map +1 -1
- package/dist/server/stream.d.ts +2 -0
- package/dist/server/stream.js +154 -114
- package/dist/server/stream.js.map +1 -1
- package/dist/style/css-mixin.d.ts +2 -1
- package/dist/style/css-mixin.js.map +1 -1
- package/dist/style/index.d.ts +1 -1
- package/dist/style/layers.d.ts +2 -0
- package/dist/style/layers.js +3 -0
- package/dist/style/layers.js.map +1 -0
- package/dist/style/stylesheet.d.ts +13 -11
- package/dist/style/stylesheet.js +69 -8
- package/dist/style/stylesheet.js.map +1 -1
- package/dist/theme/contract.d.ts +24 -222
- package/dist/theme/contract.js +2 -2
- package/dist/theme/contract.js.map +1 -1
- package/dist/theme/glyph-contract.d.ts +1 -3
- package/dist/theme/glyph-contract.js.map +1 -1
- package/dist/theme/presets/rmx-01/index.d.ts +4 -2
- package/dist/theme/presets/rmx-01/index.js.map +1 -1
- package/dist/theme/runtime.js +4 -1
- package/dist/theme/runtime.js.map +1 -1
- package/dist/utils/scroll-lock.d.ts +3 -3
- package/dist/utils/scroll-lock.js.map +1 -1
- package/package.json +3 -3
- package/src/animation/README.md +316 -0
- package/src/animation/animate-layout-mixin.ts +79 -71
- package/src/animation/spring.ts +21 -9
- package/src/components/accordion/README.md +166 -0
- package/src/components/accordion/accordion.tsx +14 -14
- package/src/components/accordion/demos/card.demo.tsx +113 -0
- package/src/components/accordion/demos/multiple.demo.tsx +56 -0
- package/src/components/accordion/demos/overview.demo.tsx +56 -0
- package/src/components/anchor/README.md +153 -0
- package/src/components/anchor/anchor.ts +1 -1
- package/src/components/breadcrumbs/README.md +55 -0
- package/src/components/breadcrumbs/breadcrumbs.tsx +1 -3
- package/src/components/breadcrumbs/demos/basic.demo.tsx +17 -0
- package/src/components/breadcrumbs/demos/separator.demo.tsx +18 -0
- package/src/components/button/README.md +4 -4
- package/src/components/button/button.tsx +118 -20
- package/src/components/button/demos/aliases.demo.tsx +27 -0
- package/src/components/button/demos/basic.demo.tsx +30 -0
- package/src/components/button/demos/states.demo.tsx +52 -0
- package/src/components/combobox/README.md +1 -1
- package/src/components/combobox/combobox.tsx +37 -21
- package/src/components/combobox/demos/overview.demo.tsx +199 -0
- package/src/components/glyph/README.md +72 -0
- package/src/components/glyph/glyph.tsx +2 -2
- package/src/components/listbox/README.md +115 -0
- package/src/components/listbox/demos/overview.demo.tsx +101 -0
- package/src/components/listbox/listbox.ts +106 -110
- package/src/components/menu/README.md +96 -0
- package/src/components/menu/demos/bubbling.demo.tsx +34 -0
- package/src/components/menu/demos/overview.demo.tsx +76 -0
- package/src/components/menu/menu.tsx +61 -55
- package/src/components/popover/README.md +3 -3
- package/src/components/popover/demos/overview.demo.tsx +143 -0
- package/src/components/popover/popover.ts +90 -79
- package/src/components/select/README.md +107 -0
- package/src/components/select/demos/deconstructed.demo.tsx +95 -0
- package/src/components/select/demos/overview.demo.tsx +51 -0
- package/src/components/select/select.tsx +53 -36
- package/src/components/tabs/tabs.tsx +10 -5
- package/src/index.ts +2 -1
- package/src/runtime/component.ts +122 -88
- package/src/runtime/core/attributes.ts +118 -0
- package/src/runtime/core/children.ts +42 -0
- package/src/runtime/core/props.ts +187 -0
- package/src/runtime/core/vnode.ts +48 -0
- package/src/runtime/create-element.ts +2 -1
- package/src/runtime/diff-dom.ts +59 -12
- package/src/runtime/diff-props.ts +2 -187
- package/src/runtime/dom.ts +20 -9
- package/src/runtime/frame.ts +71 -55
- package/src/runtime/jsx.ts +3 -30
- package/src/runtime/mixins/link-mixin.ts +88 -86
- package/src/runtime/mixins/mixin.ts +18 -5
- package/src/runtime/mixins/on-mixin.ts +20 -12
- package/src/runtime/mixins/ref-mixin.ts +4 -5
- package/src/runtime/navigation.ts +10 -1
- package/src/runtime/reconcile.ts +563 -223
- package/src/runtime/run.ts +17 -1
- package/src/runtime/scheduler.ts +20 -20
- package/src/runtime/stream-protocol.ts +27 -0
- package/src/runtime/svg-attributes.ts +1 -0
- package/src/runtime/to-vnode.ts +7 -10
- package/src/runtime/vnode.ts +16 -9
- package/src/server/README.md +90 -0
- package/src/server/stream.ts +176 -124
- package/src/style/css-mixin.ts +6 -1
- package/src/style/index.ts +1 -2
- package/src/style/layers.ts +2 -0
- package/src/style/stylesheet.ts +88 -11
- package/src/test/README.md +107 -0
- package/src/test/utils.ts +3 -1
- package/src/theme/README.md +103 -0
- package/src/theme/contract.ts +37 -5
- package/src/theme/glyph-contract.ts +3 -1
- package/src/theme/presets/rmx-01/index.ts +4 -2
- package/src/theme/runtime.ts +4 -1
- package/src/utils/scroll-lock/README.md +33 -0
- package/src/utils/scroll-lock.ts +7 -3
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// @jsxRuntime classic
|
|
2
|
-
// @jsx createElement
|
|
3
1
|
import {
|
|
4
2
|
attrs,
|
|
5
3
|
createElement,
|
|
@@ -8,8 +6,10 @@ import {
|
|
|
8
6
|
on,
|
|
9
7
|
ref,
|
|
10
8
|
type CSSMixinDescriptor,
|
|
9
|
+
type Dispatched,
|
|
11
10
|
type ElementProps,
|
|
12
11
|
type Handle,
|
|
12
|
+
type MixinFactory,
|
|
13
13
|
type Props,
|
|
14
14
|
type RemixNode,
|
|
15
15
|
} from '@remix-run/ui'
|
|
@@ -32,7 +32,10 @@ const MENU_FLASH_DURATION_MS = 60
|
|
|
32
32
|
const SUBMENU_OPEN_DELAY_MS = 300
|
|
33
33
|
const SUBMENU_ANCHOR_RELATIVE_TO = '[role="menu"] > [role^="menuitem"]'
|
|
34
34
|
|
|
35
|
-
type MenuSelectHandler = (
|
|
35
|
+
type MenuSelectHandler<target extends HTMLElement> = (
|
|
36
|
+
event: Dispatched<MenuSelectEvent, target>,
|
|
37
|
+
signal: AbortSignal,
|
|
38
|
+
) => void | Promise<void>
|
|
36
39
|
|
|
37
40
|
const menuButtonCss: CSSMixinDescriptor = css({
|
|
38
41
|
display: 'grid',
|
|
@@ -219,19 +222,8 @@ declare global {
|
|
|
219
222
|
type MenuItemType = 'item' | 'checkbox' | 'radio'
|
|
220
223
|
type CloseAnimation = 'fade' | 'none'
|
|
221
224
|
type OpenStrategy = 'first' | 'last' | 'list' | 'none'
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
Next = 0,
|
|
225
|
-
Previous = 1,
|
|
226
|
-
First = 2,
|
|
227
|
-
Last = 3,
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
enum State {
|
|
231
|
-
Idle = 'idle',
|
|
232
|
-
Dismissing = 'dismissing',
|
|
233
|
-
Selecting = 'selecting',
|
|
234
|
-
}
|
|
225
|
+
type NavigationStrategy = 'next' | 'previous' | 'first' | 'last'
|
|
226
|
+
type State = 'idle' | 'dismissing' | 'selecting'
|
|
235
227
|
|
|
236
228
|
export interface MenuSelectItem {
|
|
237
229
|
checked?: boolean
|
|
@@ -425,7 +417,7 @@ function focusNode(node: HTMLElement | undefined) {
|
|
|
425
417
|
}
|
|
426
418
|
}
|
|
427
419
|
|
|
428
|
-
function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
420
|
+
function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>): () => RemixNode {
|
|
429
421
|
let parent = handle.context.get(MenuProvider)
|
|
430
422
|
|
|
431
423
|
let activeId: string | null = null
|
|
@@ -435,7 +427,7 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
435
427
|
let items: RegisteredMenuItem[] = []
|
|
436
428
|
let listRef: HTMLElement | undefined
|
|
437
429
|
let open = false
|
|
438
|
-
let state =
|
|
430
|
+
let state: State = 'idle'
|
|
439
431
|
let suppressNextPointerLeaveClear = false
|
|
440
432
|
let surfaceRef: HTMLElement | undefined
|
|
441
433
|
let triggerId: string | undefined
|
|
@@ -487,7 +479,7 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
487
479
|
strategy = 'list',
|
|
488
480
|
focus = strategy !== 'none',
|
|
489
481
|
}: OpenMenuOptions = {}) {
|
|
490
|
-
if (state !==
|
|
482
|
+
if (state !== 'idle') {
|
|
491
483
|
return
|
|
492
484
|
}
|
|
493
485
|
|
|
@@ -538,9 +530,9 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
538
530
|
open = false
|
|
539
531
|
if (animation === 'none') {
|
|
540
532
|
activeId = null
|
|
541
|
-
state =
|
|
542
|
-
} else if (wasOpen && state ===
|
|
543
|
-
state =
|
|
533
|
+
state = 'idle'
|
|
534
|
+
} else if (wasOpen && state === 'idle') {
|
|
535
|
+
state = 'dismissing'
|
|
544
536
|
}
|
|
545
537
|
updates.push(handle.update())
|
|
546
538
|
}
|
|
@@ -561,8 +553,8 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
561
553
|
shouldUpdate = true
|
|
562
554
|
}
|
|
563
555
|
|
|
564
|
-
if (state !==
|
|
565
|
-
state =
|
|
556
|
+
if (state !== 'idle') {
|
|
557
|
+
state = 'idle'
|
|
566
558
|
shouldUpdate = true
|
|
567
559
|
}
|
|
568
560
|
|
|
@@ -630,7 +622,7 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
630
622
|
}
|
|
631
623
|
|
|
632
624
|
function highlight(id: string | null, { focus = false }: HighlightOptions = {}) {
|
|
633
|
-
if (state !==
|
|
625
|
+
if (state !== 'idle') {
|
|
634
626
|
return
|
|
635
627
|
}
|
|
636
628
|
|
|
@@ -673,7 +665,7 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
673
665
|
}
|
|
674
666
|
|
|
675
667
|
function navigate(strategy: NavigationStrategy) {
|
|
676
|
-
if (state !==
|
|
668
|
+
if (state !== 'idle') {
|
|
677
669
|
return
|
|
678
670
|
}
|
|
679
671
|
|
|
@@ -682,22 +674,22 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
682
674
|
let nextItem: RegisteredMenuItem | undefined
|
|
683
675
|
|
|
684
676
|
switch (strategy) {
|
|
685
|
-
case
|
|
677
|
+
case 'next':
|
|
686
678
|
nextItem =
|
|
687
679
|
activeIndex === -1
|
|
688
680
|
? interactableItems[0]
|
|
689
681
|
: (interactableItems[activeIndex + 1] ?? interactableItems[activeIndex])
|
|
690
682
|
break
|
|
691
|
-
case
|
|
683
|
+
case 'previous':
|
|
692
684
|
nextItem =
|
|
693
685
|
activeIndex === -1
|
|
694
686
|
? interactableItems[interactableItems.length - 1]
|
|
695
687
|
: interactableItems[activeIndex - 1]
|
|
696
688
|
break
|
|
697
|
-
case
|
|
689
|
+
case 'first':
|
|
698
690
|
nextItem = interactableItems[0]
|
|
699
691
|
break
|
|
700
|
-
case
|
|
692
|
+
case 'last':
|
|
701
693
|
nextItem = interactableItems[interactableItems.length - 1]
|
|
702
694
|
break
|
|
703
695
|
}
|
|
@@ -708,7 +700,7 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
708
700
|
}
|
|
709
701
|
|
|
710
702
|
function highlightSearchMatch(text: string) {
|
|
711
|
-
if (state !==
|
|
703
|
+
if (state !== 'idle') {
|
|
712
704
|
return
|
|
713
705
|
}
|
|
714
706
|
|
|
@@ -727,7 +719,7 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
727
719
|
}
|
|
728
720
|
|
|
729
721
|
async function activateItem(id: string) {
|
|
730
|
-
if (state !==
|
|
722
|
+
if (state !== 'idle') {
|
|
731
723
|
return
|
|
732
724
|
}
|
|
733
725
|
|
|
@@ -744,7 +736,7 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
744
736
|
let committedChecked =
|
|
745
737
|
item.type === 'checkbox' ? !item.checked : item.type === 'radio' ? true : undefined
|
|
746
738
|
|
|
747
|
-
state =
|
|
739
|
+
state = 'selecting'
|
|
748
740
|
activeId = item.id
|
|
749
741
|
flashState = item.type === 'item' ? { id: item.id } : { checked: committedChecked, id: item.id }
|
|
750
742
|
let signal = await handle.update()
|
|
@@ -776,7 +768,7 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
776
768
|
|
|
777
769
|
await closeAll()
|
|
778
770
|
|
|
779
|
-
state =
|
|
771
|
+
state = 'idle'
|
|
780
772
|
signal = await handle.update()
|
|
781
773
|
if (signal.aborted) {
|
|
782
774
|
return
|
|
@@ -792,7 +784,7 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
792
784
|
}
|
|
793
785
|
|
|
794
786
|
async function openActiveSubmenu() {
|
|
795
|
-
if (state !==
|
|
787
|
+
if (state !== 'idle') {
|
|
796
788
|
return
|
|
797
789
|
}
|
|
798
790
|
|
|
@@ -966,8 +958,8 @@ function MenuProvider(handle: Handle<MenuProviderProps, MenuContextValue>) {
|
|
|
966
958
|
}
|
|
967
959
|
}
|
|
968
960
|
|
|
969
|
-
const triggerMixin
|
|
970
|
-
(handle) => {
|
|
961
|
+
const triggerMixin: MixinFactory<HTMLElement, [options?: MenuTriggerOptions], ElementProps> =
|
|
962
|
+
createMixin<HTMLElement, [options?: MenuTriggerOptions], ElementProps>((handle) => {
|
|
971
963
|
let context = handle.context.get(MenuProvider)
|
|
972
964
|
|
|
973
965
|
return (options = {}) => [
|
|
@@ -1014,10 +1006,13 @@ const triggerMixin = createMixin<HTMLElement, [options?: MenuTriggerOptions], El
|
|
|
1014
1006
|
}
|
|
1015
1007
|
}),
|
|
1016
1008
|
]
|
|
1017
|
-
}
|
|
1018
|
-
)
|
|
1009
|
+
})
|
|
1019
1010
|
|
|
1020
|
-
const popoverMixin
|
|
1011
|
+
const popoverMixin: MixinFactory<HTMLElement, [], ElementProps> = createMixin<
|
|
1012
|
+
HTMLElement,
|
|
1013
|
+
[],
|
|
1014
|
+
ElementProps
|
|
1015
|
+
>((handle) => {
|
|
1021
1016
|
let context = handle.context.get(MenuProvider)
|
|
1022
1017
|
|
|
1023
1018
|
return () => [
|
|
@@ -1054,7 +1049,11 @@ const popoverMixin = createMixin<HTMLElement, [], ElementProps>((handle) => {
|
|
|
1054
1049
|
]
|
|
1055
1050
|
})
|
|
1056
1051
|
|
|
1057
|
-
const listMixin
|
|
1052
|
+
const listMixin: MixinFactory<HTMLElement, [], ElementProps> = createMixin<
|
|
1053
|
+
HTMLElement,
|
|
1054
|
+
[],
|
|
1055
|
+
ElementProps
|
|
1056
|
+
>((handle) => {
|
|
1058
1057
|
let context = handle.context.get(MenuProvider)
|
|
1059
1058
|
|
|
1060
1059
|
return () => [
|
|
@@ -1102,22 +1101,22 @@ const listMixin = createMixin<HTMLElement, [], ElementProps>((handle) => {
|
|
|
1102
1101
|
case 'ArrowDown':
|
|
1103
1102
|
event.preventDefault()
|
|
1104
1103
|
event.stopPropagation()
|
|
1105
|
-
context.navigate(
|
|
1104
|
+
context.navigate('next')
|
|
1106
1105
|
return
|
|
1107
1106
|
case 'ArrowUp':
|
|
1108
1107
|
event.preventDefault()
|
|
1109
1108
|
event.stopPropagation()
|
|
1110
|
-
context.navigate(
|
|
1109
|
+
context.navigate('previous')
|
|
1111
1110
|
return
|
|
1112
1111
|
case 'Home':
|
|
1113
1112
|
event.preventDefault()
|
|
1114
1113
|
event.stopPropagation()
|
|
1115
|
-
context.navigate(
|
|
1114
|
+
context.navigate('first')
|
|
1116
1115
|
return
|
|
1117
1116
|
case 'End':
|
|
1118
1117
|
event.preventDefault()
|
|
1119
1118
|
event.stopPropagation()
|
|
1120
|
-
context.navigate(
|
|
1119
|
+
context.navigate('last')
|
|
1121
1120
|
return
|
|
1122
1121
|
case 'Enter':
|
|
1123
1122
|
case ' ':
|
|
@@ -1155,7 +1154,11 @@ const listMixin = createMixin<HTMLElement, [], ElementProps>((handle) => {
|
|
|
1155
1154
|
]
|
|
1156
1155
|
})
|
|
1157
1156
|
|
|
1158
|
-
const itemMixin
|
|
1157
|
+
const itemMixin: MixinFactory<HTMLElement, [options: MenuItemOptions], ElementProps> = createMixin<
|
|
1158
|
+
HTMLElement,
|
|
1159
|
+
[options: MenuItemOptions],
|
|
1160
|
+
ElementProps
|
|
1161
|
+
>((handle) => {
|
|
1159
1162
|
let itemRef: HTMLElement | undefined
|
|
1160
1163
|
|
|
1161
1164
|
handle.queueTask((node) => {
|
|
@@ -1235,11 +1238,11 @@ const itemMixin = createMixin<HTMLElement, [options: MenuItemOptions], ElementPr
|
|
|
1235
1238
|
}
|
|
1236
1239
|
})
|
|
1237
1240
|
|
|
1238
|
-
const submenuTriggerMixin
|
|
1241
|
+
const submenuTriggerMixin: MixinFactory<
|
|
1239
1242
|
HTMLElement,
|
|
1240
1243
|
[options: SubmenuTriggerOptions],
|
|
1241
1244
|
ElementProps
|
|
1242
|
-
>((handle) => {
|
|
1245
|
+
> = createMixin<HTMLElement, [options: SubmenuTriggerOptions], ElementProps>((handle) => {
|
|
1243
1246
|
let itemRef: HTMLElement | undefined
|
|
1244
1247
|
let openTimeoutId = 0
|
|
1245
1248
|
let aborted = false
|
|
@@ -1312,7 +1315,7 @@ const submenuTriggerMixin = createMixin<
|
|
|
1312
1315
|
'aria-disabled': options.disabled ? 'true' : undefined,
|
|
1313
1316
|
'aria-expanded': childMenu.isOpen ? 'true' : 'false',
|
|
1314
1317
|
'aria-haspopup': 'menu',
|
|
1315
|
-
'data-submenu-state': childMenu.state ===
|
|
1318
|
+
'data-submenu-state': childMenu.state === 'idle' ? undefined : childMenu.state,
|
|
1316
1319
|
'data-highlighted': parent.activeId === handle.id ? 'true' : undefined,
|
|
1317
1320
|
}),
|
|
1318
1321
|
ref((node: HTMLElement, signal) => {
|
|
@@ -1406,8 +1409,11 @@ const menu = {
|
|
|
1406
1409
|
trigger,
|
|
1407
1410
|
} as const
|
|
1408
1411
|
|
|
1409
|
-
export function onMenuSelect
|
|
1410
|
-
|
|
1412
|
+
export function onMenuSelect<target extends HTMLElement>(
|
|
1413
|
+
handler: MenuSelectHandler<target>,
|
|
1414
|
+
captureBoolean?: boolean,
|
|
1415
|
+
): ReturnType<typeof on<target, typeof MENU_SELECT_EVENT>> {
|
|
1416
|
+
return on(MENU_SELECT_EVENT, handler, captureBoolean)
|
|
1411
1417
|
}
|
|
1412
1418
|
|
|
1413
1419
|
export interface MenuProps extends Omit<Props<'button'>, 'children'> {
|
|
@@ -1431,7 +1437,7 @@ export interface SubmenuProps
|
|
|
1431
1437
|
menuLabel?: string
|
|
1432
1438
|
}
|
|
1433
1439
|
|
|
1434
|
-
export function Menu(handle: Handle<MenuProps>) {
|
|
1440
|
+
export function Menu(handle: Handle<MenuProps>): () => RemixNode {
|
|
1435
1441
|
let buttonRef: HTMLButtonElement | undefined
|
|
1436
1442
|
|
|
1437
1443
|
return () => {
|
|
@@ -1478,7 +1484,7 @@ export function Menu(handle: Handle<MenuProps>) {
|
|
|
1478
1484
|
}
|
|
1479
1485
|
}
|
|
1480
1486
|
|
|
1481
|
-
export function MenuList(handle: Handle<MenuListProps>) {
|
|
1487
|
+
export function MenuList(handle: Handle<MenuListProps>): () => RemixNode {
|
|
1482
1488
|
return () => {
|
|
1483
1489
|
let { children, mix, ...divProps } = handle.props
|
|
1484
1490
|
|
|
@@ -1492,7 +1498,7 @@ export function MenuList(handle: Handle<MenuListProps>) {
|
|
|
1492
1498
|
}
|
|
1493
1499
|
}
|
|
1494
1500
|
|
|
1495
|
-
export function MenuItem(handle: Handle<MenuItemProps>) {
|
|
1501
|
+
export function MenuItem(handle: Handle<MenuItemProps>): () => RemixNode {
|
|
1496
1502
|
return () => {
|
|
1497
1503
|
let { checked, children, disabled, label, mix, name, searchValue, type, value, ...divProps } =
|
|
1498
1504
|
handle.props
|
|
@@ -1515,7 +1521,7 @@ export function MenuItem(handle: Handle<MenuItemProps>) {
|
|
|
1515
1521
|
}
|
|
1516
1522
|
}
|
|
1517
1523
|
|
|
1518
|
-
export function Submenu(handle: Handle<SubmenuProps>) {
|
|
1524
|
+
export function Submenu(handle: Handle<SubmenuProps>): () => RemixNode {
|
|
1519
1525
|
return () => {
|
|
1520
1526
|
let { children, disabled, label, listProps, menuLabel, mix, searchValue, value, ...divProps } =
|
|
1521
1527
|
handle.props
|
|
@@ -8,9 +8,9 @@ Use it for custom surfaces like filters, inspectors, and view options. Higher-le
|
|
|
8
8
|
|
|
9
9
|
```tsx
|
|
10
10
|
import { css, on, type Handle } from 'remix/ui'
|
|
11
|
-
import { Button } from '
|
|
12
|
-
import { Glyph } from '
|
|
13
|
-
import { popover } from '
|
|
11
|
+
import { Button } from 'remix/ui/button'
|
|
12
|
+
import { Glyph } from 'remix/ui/glyph'
|
|
13
|
+
import { popover } from 'remix/ui/popover'
|
|
14
14
|
|
|
15
15
|
export function ViewOptions(handle: Handle) {
|
|
16
16
|
let open = false
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { css, on, type Handle } from '@remix-run/ui'
|
|
2
|
+
import { Button } from '@remix-run/ui/button'
|
|
3
|
+
import { Glyph } from '@remix-run/ui/glyph'
|
|
4
|
+
import * as popover from '@remix-run/ui/popover'
|
|
5
|
+
import { Option, Select } from '@remix-run/ui/select'
|
|
6
|
+
import { theme } from '@remix-run/ui/theme'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @name Popover Overview
|
|
10
|
+
* @description A popover panel anchored to a trigger button, containing form controls and a close action.
|
|
11
|
+
*/
|
|
12
|
+
export default function Example(handle: Handle) {
|
|
13
|
+
let open = false
|
|
14
|
+
|
|
15
|
+
function closePopover() {
|
|
16
|
+
open = false
|
|
17
|
+
void handle.update()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return () => (
|
|
21
|
+
<popover.Context>
|
|
22
|
+
<div mix={buttonRowCss}>
|
|
23
|
+
<Button
|
|
24
|
+
endIcon={<Glyph name="chevronDown" />}
|
|
25
|
+
mix={[
|
|
26
|
+
popover.anchor({ placement: 'bottom' }),
|
|
27
|
+
popover.focusOnHide(),
|
|
28
|
+
on('click', () => {
|
|
29
|
+
open = !open
|
|
30
|
+
void handle.update()
|
|
31
|
+
}),
|
|
32
|
+
]}
|
|
33
|
+
tone="secondary"
|
|
34
|
+
>
|
|
35
|
+
View options
|
|
36
|
+
</Button>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div
|
|
40
|
+
mix={[
|
|
41
|
+
popover.surfaceStyle,
|
|
42
|
+
popover.surface({
|
|
43
|
+
closeOnAnchorClick: false,
|
|
44
|
+
open,
|
|
45
|
+
onHide() {
|
|
46
|
+
closePopover()
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
]}
|
|
50
|
+
>
|
|
51
|
+
<div mix={[popover.contentStyle, panelCss]}>
|
|
52
|
+
<div mix={fieldCss}>
|
|
53
|
+
<label for={`${handle.id}-grouping`} mix={labelCss}>
|
|
54
|
+
Grouping
|
|
55
|
+
</label>
|
|
56
|
+
<Select
|
|
57
|
+
id={`${handle.id}-grouping`}
|
|
58
|
+
defaultLabel="No grouping"
|
|
59
|
+
defaultValue="none"
|
|
60
|
+
mix={[fieldSelectCss, popover.focusOnShow()]}
|
|
61
|
+
>
|
|
62
|
+
<Option label="No grouping" value="none" />
|
|
63
|
+
<Option label="Status" value="status" />
|
|
64
|
+
<Option label="Priority" value="priority" />
|
|
65
|
+
</Select>
|
|
66
|
+
</div>
|
|
67
|
+
|
|
68
|
+
<div mix={fieldCss}>
|
|
69
|
+
<label for={`${handle.id}-ordering`} mix={labelCss}>
|
|
70
|
+
Ordering
|
|
71
|
+
</label>
|
|
72
|
+
<Select
|
|
73
|
+
id={`${handle.id}-ordering`}
|
|
74
|
+
defaultLabel="Manual"
|
|
75
|
+
defaultValue="manual"
|
|
76
|
+
mix={fieldSelectCss}
|
|
77
|
+
>
|
|
78
|
+
<Option label="Manual" value="manual" />
|
|
79
|
+
<Option label="Newest first" value="newest" />
|
|
80
|
+
<Option label="Oldest first" value="oldest" />
|
|
81
|
+
</Select>
|
|
82
|
+
</div>
|
|
83
|
+
|
|
84
|
+
<div mix={fieldCss}>
|
|
85
|
+
<label for={`${handle.id}-closed-projects`} mix={labelCss}>
|
|
86
|
+
Show closed projects
|
|
87
|
+
</label>
|
|
88
|
+
<Select
|
|
89
|
+
id={`${handle.id}-closed-projects`}
|
|
90
|
+
defaultLabel="All"
|
|
91
|
+
defaultValue="all"
|
|
92
|
+
mix={fieldSelectCss}
|
|
93
|
+
>
|
|
94
|
+
<Option label="All" value="all" />
|
|
95
|
+
<Option label="Open only" value="open" />
|
|
96
|
+
<Option label="Closed only" value="closed" />
|
|
97
|
+
</Select>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div mix={actionsCss}>
|
|
101
|
+
<Button mix={on('click', closePopover)} tone="ghost">
|
|
102
|
+
Done
|
|
103
|
+
</Button>
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</div>
|
|
107
|
+
</popover.Context>
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const buttonRowCss = css({
|
|
112
|
+
display: 'flex',
|
|
113
|
+
justifyContent: 'flex-start',
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const panelCss = css({
|
|
117
|
+
display: 'grid',
|
|
118
|
+
gap: theme.space.md,
|
|
119
|
+
width: '22rem',
|
|
120
|
+
padding: theme.space.lg,
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
const fieldCss = css({
|
|
124
|
+
display: 'grid',
|
|
125
|
+
gap: theme.space.px,
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
const labelCss = css({
|
|
129
|
+
margin: 0,
|
|
130
|
+
fontSize: theme.fontSize.xs,
|
|
131
|
+
fontWeight: theme.fontWeight.semibold,
|
|
132
|
+
color: theme.colors.text.primary,
|
|
133
|
+
})
|
|
134
|
+
|
|
135
|
+
const fieldSelectCss = css({
|
|
136
|
+
width: '100%',
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
const actionsCss = css({
|
|
140
|
+
display: 'flex',
|
|
141
|
+
justifyContent: 'flex-end',
|
|
142
|
+
paddingTop: theme.space.xs,
|
|
143
|
+
})
|