@dxos/plugin-deck 0.8.1 → 0.8.2-main.2f9c567

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.
Files changed (93) hide show
  1. package/dist/lib/browser/{check-app-scheme-SEYECDHI.mjs → check-app-scheme-O7JPE4TM.mjs} +2 -3
  2. package/dist/lib/browser/check-app-scheme-O7JPE4TM.mjs.map +7 -0
  3. package/dist/lib/browser/{chunk-FJBMNSUC.mjs → chunk-AHTP72DY.mjs} +207 -162
  4. package/dist/lib/browser/chunk-AHTP72DY.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-E7TOEOGO.mjs +157 -0
  6. package/dist/lib/browser/chunk-E7TOEOGO.mjs.map +7 -0
  7. package/dist/lib/browser/{chunk-6ZSOFCPP.mjs → chunk-PGSJT5PG.mjs} +8 -7
  8. package/dist/lib/browser/{chunk-6ZSOFCPP.mjs.map → chunk-PGSJT5PG.mjs.map} +3 -3
  9. package/dist/lib/browser/chunk-RKYIMUKW.mjs +24 -0
  10. package/dist/lib/browser/{chunk-B4LOJUWW.mjs.map → chunk-RKYIMUKW.mjs.map} +3 -3
  11. package/dist/lib/browser/index.mjs +5 -3
  12. package/dist/lib/browser/index.mjs.map +2 -2
  13. package/dist/lib/browser/{intent-resolver-UDYKO2QW.mjs → intent-resolver-NO6L67KF.mjs} +78 -53
  14. package/dist/lib/browser/intent-resolver-NO6L67KF.mjs.map +7 -0
  15. package/dist/lib/browser/meta.json +1 -1
  16. package/dist/lib/browser/{react-root-XLXN2VEW.mjs → react-root-5RWCIUXV.mjs} +5 -5
  17. package/dist/lib/browser/{react-surface-WNGMZL7I.mjs → react-surface-DIDOPTH7.mjs} +5 -5
  18. package/dist/lib/browser/{settings-HMDGSBGO.mjs → settings-C7LX2GXF.mjs} +4 -4
  19. package/dist/lib/browser/settings-C7LX2GXF.mjs.map +7 -0
  20. package/dist/lib/browser/{state-7TN26M42.mjs → state-AX74YEJD.mjs} +6 -5
  21. package/dist/lib/browser/state-AX74YEJD.mjs.map +7 -0
  22. package/dist/lib/browser/{tools-SC6QEN7R.mjs → tools-7W7KZRAX.mjs} +7 -7
  23. package/dist/lib/browser/tools-7W7KZRAX.mjs.map +7 -0
  24. package/dist/lib/browser/types.mjs +1 -1
  25. package/dist/lib/browser/{url-handler-ODG4B6NX.mjs → url-handler-AF5SYROZ.mjs} +2 -2
  26. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  27. package/dist/types/src/capabilities/capabilities.d.ts +8 -6
  28. package/dist/types/src/capabilities/capabilities.d.ts.map +1 -1
  29. package/dist/types/src/capabilities/check-app-scheme.d.ts.map +1 -1
  30. package/dist/types/src/capabilities/index.d.ts +2 -2
  31. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  32. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  33. package/dist/types/src/capabilities/state.d.ts +5 -4
  34. package/dist/types/src/capabilities/state.d.ts.map +1 -1
  35. package/dist/types/src/capabilities/tools.d.ts.map +1 -1
  36. package/dist/types/src/components/DeckLayout/ContentEmpty.d.ts.map +1 -1
  37. package/dist/types/src/components/DeckLayout/DeckLayout.d.ts.map +1 -1
  38. package/dist/types/src/components/DeckLayout/Dialog.d.ts +3 -0
  39. package/dist/types/src/components/DeckLayout/Dialog.d.ts.map +1 -0
  40. package/dist/types/src/components/DeckLayout/Popover.d.ts +5 -0
  41. package/dist/types/src/components/DeckLayout/Popover.d.ts.map +1 -0
  42. package/dist/types/src/components/Plank/Plank.d.ts.map +1 -1
  43. package/dist/types/src/components/Plank/PlankControls.d.ts +2 -2
  44. package/dist/types/src/components/Plank/PlankControls.d.ts.map +1 -1
  45. package/dist/types/src/components/Plank/PlankError.d.ts.map +1 -1
  46. package/dist/types/src/components/Plank/PlankHeading.d.ts +3 -2
  47. package/dist/types/src/components/Plank/PlankHeading.d.ts.map +1 -1
  48. package/dist/types/src/components/Sidebar/ComplementarySidebar.d.ts.map +1 -1
  49. package/dist/types/src/components/Sidebar/Sidebar.d.ts.map +1 -1
  50. package/dist/types/src/translations.d.ts +2 -0
  51. package/dist/types/src/translations.d.ts.map +1 -1
  52. package/dist/types/src/types.d.ts +106 -104
  53. package/dist/types/src/types.d.ts.map +1 -1
  54. package/dist/types/src/util/layoutAppliesTopbar.d.ts +2 -1
  55. package/dist/types/src/util/layoutAppliesTopbar.d.ts.map +1 -1
  56. package/dist/types/src/util/useHoistStatusbar.d.ts +2 -1
  57. package/dist/types/src/util/useHoistStatusbar.d.ts.map +1 -1
  58. package/package.json +31 -29
  59. package/src/capabilities/check-app-scheme.ts +3 -5
  60. package/src/capabilities/index.ts +2 -2
  61. package/src/capabilities/intent-resolver.ts +120 -96
  62. package/src/capabilities/settings.ts +2 -2
  63. package/src/capabilities/state.ts +3 -2
  64. package/src/capabilities/tools.ts +4 -3
  65. package/src/components/DeckLayout/ContentEmpty.tsx +6 -2
  66. package/src/components/DeckLayout/DeckLayout.tsx +114 -181
  67. package/src/components/DeckLayout/Dialog.tsx +36 -0
  68. package/src/components/DeckLayout/Popover.tsx +104 -0
  69. package/src/components/Plank/Plank.tsx +6 -3
  70. package/src/components/Plank/PlankControls.tsx +40 -34
  71. package/src/components/Plank/PlankError.tsx +2 -6
  72. package/src/components/Plank/PlankHeading.tsx +12 -5
  73. package/src/components/Sidebar/ComplementarySidebar.tsx +30 -20
  74. package/src/components/Sidebar/Sidebar.tsx +5 -3
  75. package/src/translations.ts +2 -0
  76. package/src/types.ts +75 -71
  77. package/src/util/layoutAppliesTopbar.ts +8 -2
  78. package/src/util/useHoistStatusbar.ts +9 -4
  79. package/dist/lib/browser/check-app-scheme-SEYECDHI.mjs.map +0 -7
  80. package/dist/lib/browser/chunk-B4LOJUWW.mjs +0 -24
  81. package/dist/lib/browser/chunk-FJBMNSUC.mjs.map +0 -7
  82. package/dist/lib/browser/chunk-RJNCG4ND.mjs +0 -154
  83. package/dist/lib/browser/chunk-RJNCG4ND.mjs.map +0 -7
  84. package/dist/lib/browser/intent-resolver-UDYKO2QW.mjs.map +0 -7
  85. package/dist/lib/browser/settings-HMDGSBGO.mjs.map +0 -7
  86. package/dist/lib/browser/state-7TN26M42.mjs.map +0 -7
  87. package/dist/lib/browser/tools-SC6QEN7R.mjs.map +0 -7
  88. package/dist/types/src/components/DeckLayout/Fullscreen.d.ts +0 -5
  89. package/dist/types/src/components/DeckLayout/Fullscreen.d.ts.map +0 -1
  90. package/src/components/DeckLayout/Fullscreen.tsx +0 -31
  91. /package/dist/lib/browser/{react-root-XLXN2VEW.mjs.map → react-root-5RWCIUXV.mjs.map} +0 -0
  92. /package/dist/lib/browser/{react-surface-WNGMZL7I.mjs.map → react-surface-DIDOPTH7.mjs.map} +0 -0
  93. /package/dist/lib/browser/{url-handler-ODG4B6NX.mjs.map → url-handler-AF5SYROZ.mjs.map} +0 -0
@@ -17,7 +17,7 @@ import {
17
17
  } from '@dxos/react-ui';
18
18
 
19
19
  import { DECK_PLUGIN } from '../../meta';
20
- import { DeckAction } from '../../types';
20
+ import { DeckAction, type LayoutMode } from '../../types';
21
21
 
22
22
  export type PlankControlHandler = (event: DeckAction.PartAdjustment) => void;
23
23
 
@@ -34,7 +34,7 @@ export type PlankControlsProps = Omit<ButtonGroupProps, 'onClick'> & {
34
34
  variant?: 'hide-disabled' | 'default';
35
35
  close?: boolean | 'minify-start' | 'minify-end';
36
36
  capabilities: PlankCapabilities;
37
- isSolo?: boolean;
37
+ layoutMode?: LayoutMode;
38
38
  pin?: 'start' | 'end' | 'both';
39
39
  };
40
40
 
@@ -73,8 +73,7 @@ export const PlankCompanionControls = forwardRef<HTMLDivElement, PlankCompliment
73
73
  <PlankControl
74
74
  label={t('close companion label')}
75
75
  variant='ghost'
76
- // icon='ph--minus--regular'
77
- icon='ph--caret-left--regular'
76
+ icon='ph--x--regular'
78
77
  onClick={handleCloseCompanion}
79
78
  classNames={plankControlSpacing}
80
79
  />
@@ -88,35 +87,51 @@ export const PlankCompanionControls = forwardRef<HTMLDivElement, PlankCompliment
88
87
  // NOTE(thure): Pinning & unpinning are disabled indefinitely.
89
88
  export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
90
89
  (
91
- { children, classNames, variant = 'default', capabilities, isSolo, pin, close = false, onClick, ...props },
90
+ { children, classNames, variant = 'default', capabilities, layoutMode, pin, close = false, onClick, ...props },
92
91
  forwardedRef,
93
92
  ) => {
94
93
  const { t } = useTranslation(DECK_PLUGIN);
95
94
  const buttonClassNames =
96
95
  variant === 'hide-disabled' ? `disabled:hidden ${plankControlSpacing}` : plankControlSpacing;
97
96
 
97
+ const layoutIsAnySolo = !!layoutMode?.startsWith('solo');
98
+
98
99
  return (
99
100
  <ButtonGroup {...props} classNames={['app-no-drag', classNames]} ref={forwardedRef}>
100
- {/* {pin && !isSolo && ['both', 'start'].includes(pin) && (
101
- <PlankControl
102
- label={t('pin start label')}
103
- variant='ghost'
104
- classNames={buttonClassNames}
105
- onClick={() => onClick?.('pin-start')}
106
- icon='ph--caret-line-left--regular'
107
- />
108
- )} */}
109
-
110
- {capabilities.deck && capabilities.solo && (
101
+ {capabilities.deck && (
111
102
  <>
112
- <PlankControl
113
- label={isSolo ? t('show deck plank label') : t('show solo plank label')}
114
- classNames={buttonClassNames}
115
- icon={isSolo ? 'ph--corners-in--regular' : 'ph--corners-out--regular'}
116
- onClick={() => onClick?.('solo')}
117
- />
118
-
119
- {!isSolo && (
103
+ {capabilities.solo && (
104
+ <>
105
+ {layoutMode === 'solo' && (
106
+ <PlankControl
107
+ label={t('show fullscreen plank label')}
108
+ classNames={buttonClassNames}
109
+ icon='ph--corners-out--regular'
110
+ onClick={() => onClick?.('solo--fullscreen')}
111
+ />
112
+ )}
113
+ <PlankControl
114
+ label={t(
115
+ layoutMode === 'solo--fullscreen'
116
+ ? 'exit fullscreen label'
117
+ : layoutIsAnySolo
118
+ ? 'show deck plank label'
119
+ : 'show solo plank label',
120
+ )}
121
+ classNames={buttonClassNames}
122
+ icon={
123
+ layoutMode === 'solo--fullscreen'
124
+ ? 'ph--corners-in--regular'
125
+ : layoutIsAnySolo
126
+ ? 'ph--arrows-in-line-horizontal--regular'
127
+ : 'ph--arrows-out-line-horizontal--regular'
128
+ }
129
+ onClick={() => onClick?.(layoutMode === 'solo--fullscreen' ? 'solo--fullscreen' : 'solo')}
130
+ />
131
+ </>
132
+ )}
133
+
134
+ {!layoutIsAnySolo && (
120
135
  <>
121
136
  <PlankControl
122
137
  label={t('increment start label')}
@@ -137,16 +152,7 @@ export const PlankControls = forwardRef<HTMLDivElement, PlankControlsProps>(
137
152
  </>
138
153
  )}
139
154
 
140
- {/* {pin && !isSolo && ['both', 'end'].includes(pin) && (
141
- <PlankControl
142
- label={t('pin end label')}
143
- classNames={buttonClassNames}
144
- icon='ph--caret-line-right--regular'
145
- onClick={() => onClick?.('pin-end')}
146
- />
147
- )} */}
148
-
149
- {close && !isSolo && (
155
+ {close && !layoutIsAnySolo && (
150
156
  <PlankControl
151
157
  label={t(`${typeof close === 'string' ? 'minify' : 'close'} label`)}
152
158
  classNames={buttonClassNames}
@@ -6,7 +6,7 @@ import React, { useEffect, useState } from 'react';
6
6
 
7
7
  import { type Node } from '@dxos/plugin-graph';
8
8
  import { useTranslation } from '@dxos/react-ui';
9
- import { descriptionText, mx } from '@dxos/react-ui-theme';
9
+ import { descriptionMessage, mx } from '@dxos/react-ui-theme';
10
10
 
11
11
  import { PlankHeading, type PlankHeadingProps } from './PlankHeading';
12
12
  import { PlankLoading } from './PlankLoading';
@@ -19,11 +19,7 @@ export const PlankContentError = ({ error }: { error?: Error }) => {
19
19
  <div role='none' className='overflow-auto p-8 attention-surface grid place-items-center'>
20
20
  <p
21
21
  role='alert'
22
- className={mx(
23
- descriptionText,
24
- 'break-words border border-dashed border-separator rounded-lg p-8',
25
- errorString.length < 256 && 'text-lg',
26
- )}
22
+ className={mx(descriptionMessage, 'break-words rounded-lg p-8', errorString.length < 256 && 'text-lg')}
27
23
  >
28
24
  {error ? errorString : t('error fallback message')}
29
25
  </p>
@@ -13,13 +13,16 @@ import { TextTooltip } from '@dxos/react-ui-text-tooltip';
13
13
  import { PlankCompanionControls, PlankControls } from './PlankControls';
14
14
  import { parseEntryId } from '../../layout';
15
15
  import { DECK_PLUGIN } from '../../meta';
16
- import { PLANK_COMPANION_TYPE, DeckAction, type ResolvedPart } from '../../types';
16
+ import { PLANK_COMPANION_TYPE, DeckAction, type ResolvedPart, type LayoutMode } from '../../types';
17
17
  import { useBreakpoints } from '../../util';
18
18
  import { soloInlinePadding } from '../fragments';
19
19
 
20
+ const MAX_COMPANIONS = 5;
21
+
20
22
  export type PlankHeadingProps = {
21
23
  id: string;
22
24
  part: ResolvedPart;
25
+ layoutMode?: LayoutMode;
23
26
  node?: Node;
24
27
  deckEnabled?: boolean;
25
28
  canIncrementStart?: boolean;
@@ -45,6 +48,7 @@ export const PlankHeading = memo(
45
48
  pending,
46
49
  companioned,
47
50
  companions,
51
+ layoutMode,
48
52
  actions = [],
49
53
  }: PlankHeadingProps) => {
50
54
  const { t } = useTranslation(DECK_PLUGIN);
@@ -96,7 +100,7 @@ export const PlankHeading = memo(
96
100
 
97
101
  const handlePlankAction = useCallback(
98
102
  (eventType: DeckAction.PartAdjustment) => {
99
- if (eventType === 'solo') {
103
+ if (eventType.startsWith('solo')) {
100
104
  return dispatch(createIntent(DeckAction.Adjust, { type: eventType, id }));
101
105
  } else if (eventType === 'close') {
102
106
  if (part === 'complementary') {
@@ -139,9 +143,12 @@ export const PlankHeading = memo(
139
143
  return (
140
144
  <StackItem.Heading
141
145
  classNames={[
142
- 'plb-1 border-be border-separator items-stretch gap-1 sticky inline-start-12 app-drag min-is-0 layout-contain',
146
+ 'plb-1 border-be border-separator items-stretch gap-1 sticky inline-start-12 app-drag min-is-0 contain-layout',
143
147
  part === 'solo' ? soloInlinePadding : 'pli-1',
148
+ layoutMode === 'solo--fullscreen' &&
149
+ 'opacity-0 border-transparent hover:border-separator hover:opacity-100 transition-[border-color,opacity]',
144
150
  ]}
151
+ data-plank-heading
145
152
  >
146
153
  {companions && isCompanionNode ? (
147
154
  <div role='none' className='flex-1 min-is-0 overflow-x-auto scrollbar-thin flex gap-1'>
@@ -150,7 +157,7 @@ export const PlankHeading = memo(
150
157
  key={id}
151
158
  data-id={id}
152
159
  icon={icon}
153
- iconOnly={node?.id !== id}
160
+ iconOnly={companions.length > MAX_COMPANIONS && node?.id !== id}
154
161
  label={toLocalizedString(label, t)}
155
162
  size={5}
156
163
  variant={node?.id === id ? 'primary' : 'default'}
@@ -196,7 +203,7 @@ export const PlankHeading = memo(
196
203
  ) : (
197
204
  <PlankControls
198
205
  capabilities={capabilities}
199
- isSolo={part === 'solo'}
206
+ layoutMode={layoutMode}
200
207
  close={part === 'complementary' ? 'minify-end' : true}
201
208
  onClick={handlePlankAction}
202
209
  />
@@ -28,7 +28,7 @@ import { byPosition, type Position } from '@dxos/util';
28
28
  import { ToggleComplementarySidebarButton } from './SidebarButton';
29
29
  import { DeckCapabilities } from '../../capabilities';
30
30
  import { DECK_PLUGIN } from '../../meta';
31
- import { ATTENDABLE_PATH_SEPARATOR, DECK_COMPANION_TYPE } from '../../types';
31
+ import { ATTENDABLE_PATH_SEPARATOR, DECK_COMPANION_TYPE, getMode } from '../../types';
32
32
  import { layoutAppliesTopbar, useBreakpoints, useHoistStatusbar } from '../../util';
33
33
  import { PlankContentError, PlankLoading } from '../Plank';
34
34
 
@@ -65,13 +65,14 @@ export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) =>
65
65
  const { t } = useTranslation(DECK_PLUGIN);
66
66
  const { dispatchPromise: dispatch } = useIntentDispatcher();
67
67
  const layout = useCapability(DeckCapabilities.MutableDeckState);
68
+ const layoutMode = getMode(layout.deck);
68
69
  const breakpoint = useBreakpoints();
69
- const topbar = layoutAppliesTopbar(breakpoint);
70
- const hoistStatusbar = useHoistStatusbar(breakpoint);
70
+ const topbar = layoutAppliesTopbar(breakpoint, layoutMode);
71
+ const hoistStatusbar = useHoistStatusbar(breakpoint, layoutMode);
71
72
 
72
73
  const companions = useDeckCompanions();
73
- const activeCompanion = companions.find((companion) => getCompanionId(companion.id) === current) ?? companions.at(0);
74
- const activeId = getCompanionId(activeCompanion?.id ?? 'never');
74
+ const activeCompanion = companions.find((companion) => getCompanionId(companion.id) === current);
75
+ const activeId = activeCompanion && getCompanionId(activeCompanion.id);
75
76
  const [internalValue, setInternalValue] = useState(activeId);
76
77
 
77
78
  useEffect(() => {
@@ -101,6 +102,14 @@ export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) =>
101
102
  [activeCompanion?.id, activeCompanion?.data],
102
103
  );
103
104
 
105
+ useEffect(() => {
106
+ if (!activeId) {
107
+ void dispatch(
108
+ createIntent(LayoutAction.UpdateComplementary, { part: 'complementary', options: { state: 'collapsed' } }),
109
+ );
110
+ }
111
+ }, [activeId, dispatch]);
112
+
104
113
  return (
105
114
  <Main.ComplementarySidebar
106
115
  label={label}
@@ -145,21 +154,22 @@ export const ComplementarySidebar = ({ current }: ComplementarySidebarProps) =>
145
154
  <ToggleComplementarySidebarButton />
146
155
  </div>
147
156
  </div>
148
- {companions.map((companion) => (
149
- <Tabs.Tabpanel
150
- key={getCompanionId(companion.id)}
151
- value={getCompanionId(companion.id)}
152
- classNames='absolute data-[state="inactive"]:-z-[1] inset-block-0 inline-start-0 is-[calc(100%-var(--r0-size))] lg:is-[--r1-size] grid grid-cols-1 grid-rows-[var(--rail-size)_1fr_min-content] pbs-[env(safe-area-inset-top)]'
153
- {...(layout.complementarySidebarState !== 'expanded' && { inert: 'true' })}
154
- >
155
- <ComplementarySidebarPanel
156
- companion={companion}
157
- activeId={activeId}
158
- data={data}
159
- hoistStatusbar={hoistStatusbar}
160
- />
161
- </Tabs.Tabpanel>
162
- ))}
157
+ {activeId &&
158
+ companions.map((companion) => (
159
+ <Tabs.Tabpanel
160
+ key={getCompanionId(companion.id)}
161
+ value={getCompanionId(companion.id)}
162
+ classNames='absolute data-[state="inactive"]:-z-[1] inset-block-0 inline-start-0 is-[calc(100%-var(--r0-size))] lg:is-[--r1-size] grid grid-cols-1 grid-rows-[var(--rail-size)_1fr_min-content] pbs-[env(safe-area-inset-top)]'
163
+ {...(layout.complementarySidebarState !== 'expanded' && { inert: 'true' })}
164
+ >
165
+ <ComplementarySidebarPanel
166
+ companion={companion}
167
+ activeId={activeId}
168
+ data={data}
169
+ hoistStatusbar={hoistStatusbar}
170
+ />
171
+ </Tabs.Tabpanel>
172
+ ))}
163
173
  </Tabs.Root>
164
174
  </Main.ComplementarySidebar>
165
175
  );
@@ -9,15 +9,17 @@ import { type Label, Main } from '@dxos/react-ui';
9
9
 
10
10
  import { DeckCapabilities } from '../../capabilities';
11
11
  import { DECK_PLUGIN } from '../../meta';
12
+ import { getMode } from '../../types';
12
13
  import { layoutAppliesTopbar, useBreakpoints, useHoistStatusbar } from '../../util';
13
14
 
14
15
  const label = ['sidebar title', { ns: DECK_PLUGIN }] satisfies Label;
15
16
 
16
17
  export const Sidebar = () => {
17
- const { popoverAnchorId, activeDeck: current } = useCapability(DeckCapabilities.DeckState);
18
+ const { popoverAnchorId, activeDeck: current, deck } = useCapability(DeckCapabilities.DeckState);
18
19
  const breakpoint = useBreakpoints();
19
- const topbar = layoutAppliesTopbar(breakpoint);
20
- const hoistStatusbar = useHoistStatusbar(breakpoint);
20
+ const layoutMode = getMode(deck);
21
+ const topbar = layoutAppliesTopbar(breakpoint, layoutMode);
22
+ const hoistStatusbar = useHoistStatusbar(breakpoint, layoutMode);
21
23
 
22
24
  const navigationData = useMemo(
23
25
  () => ({ popoverAnchorId, topbar, hoistStatusbar, current }),
@@ -45,6 +45,8 @@ export default [
45
45
  'increment end label': 'Move to the right',
46
46
  'show deck plank label': 'Return to deck',
47
47
  'show solo plank label': 'Maximize',
48
+ 'exit fullscreen label': 'Exit fullscreen',
49
+ 'show fullscreen plank label': 'Fullscreen',
48
50
  'close label': 'Close',
49
51
  'minify label': 'Minify',
50
52
  'open companion label': 'Open companion',
package/src/types.ts CHANGED
@@ -2,8 +2,10 @@
2
2
  // Copyright 2023 DXOS.org
3
3
  //
4
4
 
5
+ import { Schema } from 'effect';
6
+
5
7
  import { LayoutAction } from '@dxos/app-framework';
6
- import { S } from '@dxos/echo-schema';
8
+ import { type DeepReadonly } from '@dxos/util';
7
9
 
8
10
  import { DECK_PLUGIN } from './meta';
9
11
 
@@ -22,33 +24,33 @@ export type Overscroll = (typeof OverscrollOptions)[number];
22
24
  export type Part = 'solo' | 'deck' | 'complementary';
23
25
  export type ResolvedPart = Part | 'solo-primary' | 'solo-companion';
24
26
 
25
- export const DeckSettingsSchema = S.Struct({
26
- showHints: S.optional(S.Boolean),
27
- enableDeck: S.optional(S.Boolean),
28
- enableNativeRedirect: S.optional(S.Boolean),
29
- enableStatusbar: S.optional(S.Boolean),
30
- newPlankPositioning: S.optional(S.Literal(...NewPlankPositions)),
31
- overscroll: S.optional(S.Literal(...OverscrollOptions)),
32
- }).pipe(S.mutable);
33
- export type DeckSettingsProps = S.Schema.Type<typeof DeckSettingsSchema>;
27
+ export const DeckSettingsSchema = Schema.Struct({
28
+ showHints: Schema.optional(Schema.Boolean),
29
+ enableDeck: Schema.optional(Schema.Boolean),
30
+ enableNativeRedirect: Schema.optional(Schema.Boolean),
31
+ enableStatusbar: Schema.optional(Schema.Boolean),
32
+ newPlankPositioning: Schema.optional(Schema.Literal(...NewPlankPositions)),
33
+ overscroll: Schema.optional(Schema.Literal(...OverscrollOptions)),
34
+ }).pipe(Schema.mutable);
35
+ export type DeckSettingsProps = Schema.Schema.Type<typeof DeckSettingsSchema>;
34
36
 
35
- export const PlankSizing = S.Record({ key: S.String, value: S.Number });
36
- export type PlankSizing = S.Schema.Type<typeof PlankSizing>;
37
+ export const PlankSizing = Schema.Record({ key: Schema.String, value: Schema.Number });
38
+ export type PlankSizing = Schema.Schema.Type<typeof PlankSizing>;
37
39
 
38
40
  // State of an individual deck.
39
- export const DeckState = S.Struct({
41
+ export const DeckState = Schema.Struct({
40
42
  /** If false, the deck has not yet left solo mode and new planks should be soloed. */
41
- initialized: S.Boolean,
42
- active: S.mutable(S.Array(S.String)),
43
+ initialized: Schema.Boolean,
44
+ active: Schema.mutable(Schema.Array(Schema.String)),
43
45
  // TODO(wittjosiah): Piping into both mutable and optional caused invalid typescript output.
44
- activeCompanions: S.optional(S.mutable(S.Record({ key: S.String, value: S.String }))),
45
- inactive: S.mutable(S.Array(S.String)),
46
- solo: S.optional(S.String),
47
- fullscreen: S.Boolean,
48
- plankSizing: S.mutable(PlankSizing),
49
- companionFrameSizing: S.mutable(PlankSizing),
46
+ activeCompanions: Schema.optional(Schema.mutable(Schema.Record({ key: Schema.String, value: Schema.String }))),
47
+ inactive: Schema.mutable(Schema.Array(Schema.String)),
48
+ solo: Schema.optional(Schema.String),
49
+ fullscreen: Schema.Boolean,
50
+ plankSizing: Schema.mutable(PlankSizing),
51
+ companionFrameSizing: Schema.mutable(PlankSizing),
50
52
  });
51
- export type DeckState = S.Schema.Type<typeof DeckState>;
53
+ export type DeckState = Schema.Schema.Type<typeof DeckState>;
52
54
 
53
55
  export const defaultDeck: DeckState = {
54
56
  initialized: false,
@@ -61,84 +63,86 @@ export const defaultDeck: DeckState = {
61
63
  companionFrameSizing: {},
62
64
  };
63
65
 
64
- const LayoutMode = S.Literal('deck', 'solo', 'fullscreen');
65
- export type LayoutMode = S.Schema.Type<typeof LayoutMode>;
66
- export const isLayoutMode = (value: any): value is LayoutMode => S.is(LayoutMode)(value);
66
+ const LayoutMode = Schema.Literal('deck', 'solo', 'solo--fullscreen');
67
+ export type LayoutMode = Schema.Schema.Type<typeof LayoutMode>;
68
+ export const isLayoutMode = (value: any): value is LayoutMode => Schema.is(LayoutMode)(value);
67
69
 
68
- export const getMode = (deck: DeckState): LayoutMode => {
70
+ export const getMode = (deck: DeckState | DeepReadonly<DeckState>): LayoutMode => {
69
71
  if (deck.solo) {
70
- return deck.fullscreen ? 'fullscreen' : 'solo';
72
+ return deck.fullscreen ? 'solo--fullscreen' : 'solo';
71
73
  }
72
74
 
73
75
  return 'deck';
74
76
  };
75
77
 
76
78
  // State of the deck plugin.
77
- export const DeckPluginState = S.Struct({
78
- sidebarState: S.Literal('closed', 'collapsed', 'expanded'),
79
- complementarySidebarState: S.Literal('closed', 'collapsed', 'expanded'),
80
- complementarySidebarPanel: S.optional(S.String),
81
-
82
- dialogOpen: S.Boolean,
79
+ export const DeckPluginState = Schema.Struct({
80
+ sidebarState: Schema.Literal('closed', 'collapsed', 'expanded'),
81
+ complementarySidebarState: Schema.Literal('closed', 'collapsed', 'expanded'),
82
+ complementarySidebarPanel: Schema.optional(Schema.String),
83
+
84
+ dialogOpen: Schema.Boolean,
85
+ dialogBlockAlign: Schema.optional(Schema.Literal('start', 'center', 'end')),
86
+ dialogType: Schema.optional(Schema.Literal('default', 'alert')),
83
87
  /** Data to be passed to the dialog Surface. */
84
- dialogContent: S.optional(S.Any),
85
- dialogBlockAlign: S.optional(S.Literal('start', 'center', 'end')),
86
- dialogType: S.optional(S.Literal('default', 'alert')),
88
+ dialogContent: Schema.optional(Schema.Any),
87
89
 
88
- popoverOpen: S.Boolean,
89
- popoverSide: S.optional(S.Literal('top', 'right', 'bottom', 'left')),
90
+ popoverOpen: Schema.Boolean,
91
+ popoverSide: Schema.optional(Schema.Literal('top', 'right', 'bottom', 'left')),
92
+ popoverAnchor: Schema.optional(Schema.Any),
93
+ popoverAnchorId: Schema.optional(Schema.String),
90
94
  /** Data to be passed to the popover Surface. */
91
- popoverContent: S.optional(S.Any),
92
- popoverAnchorId: S.optional(S.String),
95
+ popoverContent: Schema.optional(Schema.Any),
93
96
 
94
- toasts: S.mutable(S.Array(LayoutAction.Toast)),
95
- currentUndoId: S.optional(S.String),
97
+ toasts: Schema.mutable(Schema.Array(LayoutAction.Toast)),
98
+ currentUndoId: Schema.optional(Schema.String),
96
99
 
97
- activeDeck: S.String,
98
- previousDeck: S.String,
99
- decks: S.mutable(S.Record({ key: S.String, value: S.mutable(DeckState) })),
100
- previousMode: S.mutable(S.Record({ key: S.String, value: LayoutMode })),
101
- deck: S.mutable(DeckState),
100
+ activeDeck: Schema.String,
101
+ previousDeck: Schema.String,
102
+ decks: Schema.mutable(Schema.Record({ key: Schema.String, value: Schema.mutable(DeckState) })),
103
+ previousMode: Schema.mutable(Schema.Record({ key: Schema.String, value: LayoutMode })),
104
+ deck: Schema.mutable(DeckState),
102
105
 
103
106
  /** The identifier of a component to scroll into view when it is mounted. */
104
- scrollIntoView: S.optional(S.String),
105
- }).pipe(S.mutable);
107
+ scrollIntoView: Schema.optional(Schema.String),
108
+ }).pipe(Schema.mutable);
106
109
 
107
- export type DeckPluginState = S.Schema.Type<typeof DeckPluginState>;
110
+ export type DeckPluginState = Schema.Schema.Type<typeof DeckPluginState>;
108
111
 
109
112
  export const DECK_ACTION = `${DECK_PLUGIN}/action`;
110
113
 
111
114
  export namespace DeckAction {
112
- const PartAdjustmentSchema = S.Union(
113
- S.Literal('close').annotations({ description: 'Close the plank.' }),
114
- S.Literal('companion').annotations({ description: 'Open the companion plank.' }),
115
- S.Literal('solo').annotations({ description: 'Solo the plank.' }),
116
- S.Literal('increment-start').annotations({ description: 'Move the plank towards the start of the deck.' }),
117
- S.Literal('increment-end').annotations({ description: 'Move the plank towards the end of the deck.' }),
115
+ const PartAdjustmentSchema = Schema.Union(
116
+ Schema.Literal('close').annotations({ description: 'Close the plank.' }),
117
+ Schema.Literal('companion').annotations({ description: 'Open the companion plank.' }),
118
+ Schema.Literal('solo').annotations({ description: 'Solo the plank.' }),
119
+ Schema.Literal('solo--fullscreen').annotations({ description: 'Fullscreen the plank.' }),
120
+ Schema.Literal('increment-start').annotations({ description: 'Move the plank towards the start of the deck.' }),
121
+ Schema.Literal('increment-end').annotations({ description: 'Move the plank towards the end of the deck.' }),
118
122
  );
119
- export type PartAdjustment = S.Schema.Type<typeof PartAdjustmentSchema>;
120
- export const Adjustment = S.mutable(S.Struct({ id: S.String, type: PartAdjustmentSchema }));
121
- export type Adjustment = S.Schema.Type<typeof Adjustment>;
123
+ export type PartAdjustment = Schema.Schema.Type<typeof PartAdjustmentSchema>;
124
+ export const Adjustment = Schema.mutable(Schema.Struct({ id: Schema.String, type: PartAdjustmentSchema }));
125
+ export type Adjustment = Schema.Schema.Type<typeof Adjustment>;
122
126
 
123
127
  // An atomic transaction to apply to the deck, describing which element to move to which location.
124
- export class Adjust extends S.TaggedClass<Adjust>()(`${DECK_ACTION}/adjust`, {
128
+ export class Adjust extends Schema.TaggedClass<Adjust>()(`${DECK_ACTION}/adjust`, {
125
129
  input: Adjustment,
126
- output: S.Void,
130
+ output: Schema.Void,
127
131
  }) {}
128
132
 
129
- export class UpdatePlankSize extends S.TaggedClass<UpdatePlankSize>()(`${DECK_ACTION}/update-plank-size`, {
130
- input: S.Struct({
131
- id: S.String,
132
- size: S.Number,
133
+ export class UpdatePlankSize extends Schema.TaggedClass<UpdatePlankSize>()(`${DECK_ACTION}/update-plank-size`, {
134
+ input: Schema.Struct({
135
+ id: Schema.String,
136
+ size: Schema.Number,
133
137
  }),
134
- output: S.Void,
138
+ output: Schema.Void,
135
139
  }) {}
136
140
 
137
- export class ChangeCompanion extends S.TaggedClass<ChangeCompanion>()(`${DECK_ACTION}/change-companion`, {
138
- input: S.Struct({
139
- primary: S.String,
140
- companion: S.Union(S.String, S.Null),
141
+ export class ChangeCompanion extends Schema.TaggedClass<ChangeCompanion>()(`${DECK_ACTION}/change-companion`, {
142
+ input: Schema.Struct({
143
+ primary: Schema.String,
144
+ companion: Schema.Union(Schema.String, Schema.Null),
141
145
  }),
142
- output: S.Void,
146
+ output: Schema.Void,
143
147
  }) {}
144
148
  }
@@ -2,6 +2,12 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- export const layoutAppliesTopbar = (breakpoint: string) => {
6
- return document.body.getAttribute('data-platform') === 'win' && breakpoint === 'desktop';
5
+ import { type LayoutMode } from '../types';
6
+
7
+ export const layoutAppliesTopbar = (breakpoint: string, layoutMode?: LayoutMode) => {
8
+ return (
9
+ document.body.getAttribute('data-platform') === 'win' &&
10
+ breakpoint === 'desktop' &&
11
+ layoutMode !== 'solo--fullscreen'
12
+ );
7
13
  };
@@ -8,13 +8,18 @@ import { Capabilities, useCapability } from '@dxos/app-framework';
8
8
  import { useThemeContext } from '@dxos/react-ui';
9
9
 
10
10
  import { DECK_PLUGIN } from '../meta';
11
- import type { DeckSettingsProps } from '../types';
11
+ import type { DeckSettingsProps, LayoutMode } from '../types';
12
12
 
13
- export const useHoistStatusbar = (breakpoint: string): boolean => {
13
+ export const useHoistStatusbar = (breakpoint: string, layoutMode?: LayoutMode): boolean => {
14
14
  const enableStatusbar = useCapability(Capabilities.SettingsStore).getStore<DeckSettingsProps>(DECK_PLUGIN)!.value
15
15
  .enableStatusbar;
16
16
  const { safeAreaPadding } = useThemeContext();
17
17
  return useMemo(() => {
18
- return breakpoint === 'desktop' && !!enableStatusbar && safeAreaPadding?.bottom === 0;
19
- }, [enableStatusbar, breakpoint, safeAreaPadding?.bottom]);
18
+ return (
19
+ breakpoint === 'desktop' &&
20
+ layoutMode !== 'solo--fullscreen' &&
21
+ !!enableStatusbar &&
22
+ safeAreaPadding?.bottom === 0
23
+ );
24
+ }, [enableStatusbar, breakpoint, safeAreaPadding?.bottom, layoutMode]);
20
25
  };
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/capabilities/check-app-scheme.ts"],
4
- "sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n//\n// Copyright 2025 DXOS.org\n//\n\nimport { Capabilities, contributes, type PluginsContext } from '@dxos/app-framework';\n\nimport { DECK_PLUGIN } from '../meta';\nimport { type DeckSettingsProps } from '../types';\n\nconst isSocket = !!(globalThis as any).__args;\n\n// TODO(mjamesderocher): Can we get this directly from Socket?\nconst appScheme = 'composer://';\n\n// TODO(mjamesderocher): Factor out as part of NavigationPlugin.\nconst checkAppScheme = (url: string) => {\n const iframe = document.createElement('iframe');\n iframe.style.display = 'none';\n document.body.appendChild(iframe);\n\n iframe.src = url + window.location.pathname.replace(/^\\/+/, '') + window.location.search;\n\n const timer = setTimeout(() => {\n document.body.removeChild(iframe);\n }, 3000);\n\n window.addEventListener('pagehide', (event) => {\n clearTimeout(timer);\n document.body.removeChild(iframe);\n });\n};\n\nexport default async (context: PluginsContext) => {\n const settingsStore = context.requestCapability(Capabilities.SettingsStore);\n const settings = settingsStore.getStore<DeckSettingsProps>(DECK_PLUGIN)?.value;\n if (!isSocket && settings?.enableNativeRedirect) {\n checkAppScheme(appScheme);\n }\n\n return contributes(Capabilities.Null, null);\n};\n"],
5
- "mappings": ";;;;;AAOA,SAASA,cAAcC,mBAAwC;AAK/D,IAAMC,WAAW,CAAC,CAAEC,WAAmBC;AAGvC,IAAMC,YAAY;AAGlB,IAAMC,iBAAiB,CAACC,QAAAA;AACtB,QAAMC,SAASC,SAASC,cAAc,QAAA;AACtCF,SAAOG,MAAMC,UAAU;AACvBH,WAASI,KAAKC,YAAYN,MAAAA;AAE1BA,SAAOO,MAAMR,MAAMS,OAAOC,SAASC,SAASC,QAAQ,QAAQ,EAAA,IAAMH,OAAOC,SAASG;AAElF,QAAMC,QAAQC,WAAW,MAAA;AACvBb,aAASI,KAAKU,YAAYf,MAAAA;EAC5B,GAAG,GAAA;AAEHQ,SAAOQ,iBAAiB,YAAY,CAACC,UAAAA;AACnCC,iBAAaL,KAAAA;AACbZ,aAASI,KAAKU,YAAYf,MAAAA;EAC5B,CAAA;AACF;AAEA,IAAA,2BAAe,OAAOmB,YAAAA;AACpB,QAAMC,gBAAgBD,QAAQE,kBAAkBC,aAAaC,aAAa;AAC1E,QAAMC,WAAWJ,cAAcK,SAA4BC,WAAAA,GAAcC;AACzE,MAAI,CAACjC,YAAY8B,UAAUI,sBAAsB;AAC/C9B,mBAAeD,SAAAA;EACjB;AAEA,SAAOgC,YAAYP,aAAaQ,MAAM,IAAA;AACxC;",
6
- "names": ["Capabilities", "contributes", "isSocket", "globalThis", "__args", "appScheme", "checkAppScheme", "url", "iframe", "document", "createElement", "style", "display", "body", "appendChild", "src", "window", "location", "pathname", "replace", "search", "timer", "setTimeout", "removeChild", "addEventListener", "event", "clearTimeout", "context", "settingsStore", "requestCapability", "Capabilities", "SettingsStore", "settings", "getStore", "DECK_PLUGIN", "value", "enableNativeRedirect", "contributes", "Null"]
7
- }
@@ -1,24 +0,0 @@
1
- // packages/plugins/plugin-deck/src/capabilities/index.ts
2
- import { lazy } from "@dxos/app-framework";
3
- var AppGraphBuilder = lazy(() => import("./app-graph-builder-VYZ4IWI3.mjs"));
4
- var CheckAppScheme = lazy(() => import("./check-app-scheme-SEYECDHI.mjs"));
5
- var LayoutIntentResolver = lazy(() => import("./intent-resolver-UDYKO2QW.mjs"));
6
- var ReactRoot = lazy(() => import("./react-root-XLXN2VEW.mjs"));
7
- var ReactSurface = lazy(() => import("./react-surface-WNGMZL7I.mjs"));
8
- var DeckSettings = lazy(() => import("./settings-HMDGSBGO.mjs"));
9
- var DeckState = lazy(() => import("./state-7TN26M42.mjs"));
10
- var Tools = lazy(() => import("./tools-SC6QEN7R.mjs"));
11
- var UrlHandler = lazy(() => import("./url-handler-ODG4B6NX.mjs"));
12
-
13
- export {
14
- AppGraphBuilder,
15
- CheckAppScheme,
16
- LayoutIntentResolver,
17
- ReactRoot,
18
- ReactSurface,
19
- DeckSettings,
20
- DeckState,
21
- Tools,
22
- UrlHandler
23
- };
24
- //# sourceMappingURL=chunk-B4LOJUWW.mjs.map