@textui/widgets 0.6.1 → 0.8.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.
Files changed (120) hide show
  1. package/dist/chart/line-chart.d.ts.map +1 -1
  2. package/dist/chart/line-chart.js +3 -2
  3. package/dist/control/select.d.ts.map +1 -1
  4. package/dist/control/select.js +4 -2
  5. package/dist/control/switch.d.ts.map +1 -1
  6. package/dist/control/switch.js +7 -2
  7. package/dist/control/text-area.d.ts +2 -0
  8. package/dist/control/text-area.d.ts.map +1 -1
  9. package/dist/control/text-area.js +16 -8
  10. package/dist/data/code-viewer.d.ts +2 -0
  11. package/dist/data/code-viewer.d.ts.map +1 -1
  12. package/dist/data/code-viewer.js +9 -1
  13. package/dist/data/index.d.ts +9 -0
  14. package/dist/data/index.d.ts.map +1 -1
  15. package/dist/data/index.js +11 -4
  16. package/dist/data/list.d.ts +9 -0
  17. package/dist/data/list.d.ts.map +1 -1
  18. package/dist/data/list.js +23 -5
  19. package/dist/data/log-viewer.d.ts.map +1 -1
  20. package/dist/data/log-viewer.js +7 -2
  21. package/dist/data/markdown-view.d.ts.map +1 -1
  22. package/dist/data/markdown-view.js +6 -2
  23. package/dist/data/pagination.d.ts.map +1 -1
  24. package/dist/data/pagination.js +6 -2
  25. package/dist/data/tree.d.ts +2 -0
  26. package/dist/data/tree.d.ts.map +1 -1
  27. package/dist/data/tree.js +8 -2
  28. package/dist/display/card.d.ts.map +1 -1
  29. package/dist/display/card.js +12 -0
  30. package/dist/display/color-text.d.ts +13 -1
  31. package/dist/display/color-text.d.ts.map +1 -1
  32. package/dist/display/color-text.js +28 -6
  33. package/dist/display/error-state.d.ts.map +1 -1
  34. package/dist/display/error-state.js +4 -3
  35. package/dist/display/font-text.d.ts +72 -0
  36. package/dist/display/font-text.d.ts.map +1 -0
  37. package/dist/display/font-text.js +35 -0
  38. package/dist/display/fonts.d.ts +138 -0
  39. package/dist/display/fonts.d.ts.map +1 -0
  40. package/dist/display/fonts.js +893 -0
  41. package/dist/display/gard.d.ts +26 -0
  42. package/dist/display/gard.d.ts.map +1 -0
  43. package/dist/display/gard.js +479 -0
  44. package/dist/display/index.d.ts +3 -0
  45. package/dist/display/index.d.ts.map +1 -1
  46. package/dist/display/index.js +7 -0
  47. package/dist/display/key-value.d.ts +25 -5
  48. package/dist/display/key-value.d.ts.map +1 -1
  49. package/dist/display/key-value.js +13 -3
  50. package/dist/display/pagga.d.ts +29 -0
  51. package/dist/display/pagga.d.ts.map +1 -0
  52. package/dist/display/pagga.js +101 -0
  53. package/dist/display/pattern.d.ts +117 -0
  54. package/dist/display/pattern.d.ts.map +1 -0
  55. package/dist/display/pattern.js +257 -0
  56. package/dist/display/spinner.d.ts +2 -0
  57. package/dist/display/spinner.d.ts.map +1 -1
  58. package/dist/display/spinner.js +3 -2
  59. package/dist/form/danger-zone.d.ts.map +1 -1
  60. package/dist/form/danger-zone.js +7 -3
  61. package/dist/form/form-actions.d.ts.map +1 -1
  62. package/dist/form/form-actions.js +3 -2
  63. package/dist/navigation/menu.d.ts +2 -0
  64. package/dist/navigation/menu.d.ts.map +1 -1
  65. package/dist/navigation/menu.js +22 -8
  66. package/dist/navigation/tabs.d.ts +2 -0
  67. package/dist/navigation/tabs.d.ts.map +1 -1
  68. package/dist/navigation/tabs.js +12 -2
  69. package/dist/overlay/command-palette.d.ts.map +1 -1
  70. package/dist/overlay/command-palette.js +55 -15
  71. package/dist/overlay/dialog.d.ts +11 -0
  72. package/dist/overlay/dialog.d.ts.map +1 -1
  73. package/dist/overlay/dialog.js +24 -1
  74. package/dist/overlay/index.d.ts.map +1 -1
  75. package/dist/overlay/index.js +11 -19
  76. package/dist/overlay/path-picker.d.ts.map +1 -1
  77. package/dist/overlay/path-picker.js +19 -11
  78. package/dist/overlay/prompt-dialog.d.ts.map +1 -1
  79. package/dist/overlay/prompt-dialog.js +5 -4
  80. package/dist/panel/index.d.ts.map +1 -1
  81. package/dist/panel/index.js +8 -7
  82. package/dist/panel/resource-panel.d.ts.map +1 -1
  83. package/dist/panel/resource-panel.js +9 -5
  84. package/dist/surface/mount-view.d.ts.map +1 -1
  85. package/dist/surface/mount-view.js +3 -2
  86. package/package.json +2 -2
  87. package/src/chart/line-chart.ts +3 -2
  88. package/src/control/select.ts +4 -2
  89. package/src/control/switch.ts +9 -2
  90. package/src/control/text-area.ts +18 -7
  91. package/src/data/code-viewer.ts +10 -1
  92. package/src/data/index.ts +12 -3
  93. package/src/data/list.ts +24 -4
  94. package/src/data/log-viewer.ts +7 -1
  95. package/src/data/markdown-view.ts +10 -1
  96. package/src/data/pagination.ts +6 -2
  97. package/src/data/tree.ts +9 -2
  98. package/src/display/card.ts +12 -0
  99. package/src/display/color-text.ts +33 -10
  100. package/src/display/error-state.ts +4 -3
  101. package/src/display/font-text.tsx +94 -0
  102. package/src/display/fonts.ts +990 -0
  103. package/src/display/gard.ts +475 -0
  104. package/src/display/index.ts +7 -0
  105. package/src/display/key-value.ts +44 -6
  106. package/src/display/pagga.ts +102 -0
  107. package/src/display/pattern.tsx +427 -0
  108. package/src/display/spinner.ts +5 -2
  109. package/src/form/danger-zone.ts +7 -3
  110. package/src/form/form-actions.ts +5 -2
  111. package/src/navigation/menu.ts +23 -8
  112. package/src/navigation/tabs.ts +13 -2
  113. package/src/overlay/command-palette.ts +66 -14
  114. package/src/overlay/dialog.ts +37 -1
  115. package/src/overlay/index.ts +11 -19
  116. package/src/overlay/path-picker.ts +23 -10
  117. package/src/overlay/prompt-dialog.ts +5 -4
  118. package/src/panel/index.ts +9 -7
  119. package/src/panel/resource-panel.ts +9 -4
  120. package/src/surface/mount-view.ts +3 -2
@@ -1,8 +1,11 @@
1
- import { defineComponent, h, stringWidth, useFocus, useInput, useState, useTheme } from '@textui/core';
1
+ import { defineComponent, h, stringWidth, useFocus, useI18n, useInput, useState, useTheme } from '@textui/core';
2
2
  import { Marquee } from '../display/index.js';
3
3
  import { TONE } from '../tone.js';
4
+ /** The name a theme styles a menu row under. See `LIST`. */
5
+ export const MENU = 'Menu';
4
6
  export const Menu = defineComponent('Menu', (props) => {
5
7
  const theme = useTheme();
8
+ const i18n = useI18n();
6
9
  const { items, onSelect, visibleRows, activeId, autoFocus, interactive = true, descriptions = 'inline', ...rest } = props;
7
10
  const focus = useFocus({ autoFocus, disabled: !interactive });
8
11
  const selectable = items.filter((i) => !i.disabled);
@@ -57,14 +60,19 @@ export const Menu = defineComponent('Menu', (props) => {
57
60
  // The description yields first, and by a lot. It is the elaboration;
58
61
  // the label is the thing being chosen, and a row reading "Accept ed…"
59
62
  // beside a full sentence has given up the wrong half.
63
+ //
64
+ // On the row under the cursor the foreground is `undefined`, not a
65
+ // token: what is written on a selection is the theme's, and a hard
66
+ // `onSelected` here would be a second answer to the same question that
67
+ // a theme restating `Menu.focused.fg` could not reach.
60
68
  item.description && !below
61
69
  ? h(Marquee, {
62
70
  content: item.description,
63
71
  active,
64
- fg: active ? 'inverted' : 'muted',
72
+ fg: active ? undefined : 'muted',
65
73
  shrink: 8,
66
74
  })
67
- : null, item.shortcut ? h('text', { content: item.shortcut, fg: active ? 'inverted' : 'subtle' }) : null,
75
+ : null, item.shortcut ? h('text', { content: item.shortcut, fg: active ? undefined : 'subtle' }) : null,
68
76
  // Present but empty means "this opens something, contents unknown" -
69
77
  // which is what the command palette knows about an argument whose
70
78
  // choices it has not resolved yet.
@@ -73,12 +81,18 @@ export const Menu = defineComponent('Menu', (props) => {
73
81
  key: item.id,
74
82
  role: 'menuitem',
75
83
  label: item.label,
84
+ styleAs: MENU,
76
85
  selected: active,
86
+ // The keyboard is the menu's, so the row is told - which is what lets
87
+ // `Menu.selected` be the dimmer fill a menu shows when something else
88
+ // has taken the keyboard, and `Menu.focused` the one it shows while
89
+ // the reader is moving through it.
90
+ focused: active && focus.focused,
77
91
  direction: 'column',
78
92
  // One background over both lines: a highlight that stopped after the
79
- // label would split the row it is highlighting in two.
80
- bg: active ? 'selected' : undefined,
81
- fg: item.disabled ? 'disabled' : active ? 'inverted' : item.tone ? TONE[item.tone] : undefined,
93
+ // label would split the row it is highlighting in two. What it is
94
+ // filled with is the theme's to say.
95
+ fg: item.disabled ? 'disabled' : active ? undefined : item.tone ? TONE[item.tone] : undefined,
82
96
  onClick: () => { if (!item.disabled)
83
97
  onSelect?.(item.id, item); },
84
98
  }, head,
@@ -93,7 +107,7 @@ export const Menu = defineComponent('Menu', (props) => {
93
107
  h(Marquee, {
94
108
  content: item.description,
95
109
  active,
96
- fg: active ? 'inverted' : 'muted',
110
+ fg: active ? undefined : 'muted',
97
111
  flex: 1,
98
112
  }))
99
113
  : null);
@@ -110,7 +124,7 @@ export const Menu = defineComponent('Menu', (props) => {
110
124
  ? [h('box', { key: `${item.id}-sep`, height: 1, fill: theme.borderChars().top, fg: 'borderSubtle' }), row]
111
125
  : [row];
112
126
  }), selectable.length === 0
113
- ? h('text', { content: ' no matches', fg: 'subtle' })
127
+ ? h('text', { content: ` ${i18n.t('textui.menu.noMatch', undefined, 'no matches')}`, fg: 'subtle' })
114
128
  : null);
115
129
  });
116
130
  /**
@@ -16,5 +16,7 @@ export interface TabsProps extends BoxProps {
16
16
  /** Take focus on mount, so the keyboard has somewhere to be. */
17
17
  autoFocus?: boolean;
18
18
  }
19
+ /** The name a theme styles a tab under. See `LIST`. */
20
+ export declare const TABS = "Tabs";
19
21
  export declare const Tabs: (props: TabsProps) => import("@textui/core").RenderOutput;
20
22
  //# sourceMappingURL=tabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/navigation/tabs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI7C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,SAAU,SAAQ,QAAQ;IACzC,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wDAAwD;IACxD,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,OAAO,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,eAAO,MAAM,IAAI,2DAiDf,CAAC"}
1
+ {"version":3,"file":"tabs.d.ts","sourceRoot":"","sources":["../../src/navigation/tabs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAI7C,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,SAAU,SAAQ,QAAQ;IACzC,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wDAAwD;IACxD,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,GAAG,OAAO,CAAC;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gEAAgE;IAChE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,uDAAuD;AACvD,eAAO,MAAM,IAAI,SAAS,CAAC;AAE3B,eAAO,MAAM,IAAI,2DAyDf,CAAC"}
@@ -1,4 +1,6 @@
1
1
  import { defineComponent, h, useFocus, useInput } from '@textui/core';
2
+ /** The name a theme styles a tab under. See `LIST`. */
3
+ export const TABS = 'Tabs';
2
4
  export const Tabs = defineComponent('Tabs', (props) => {
3
5
  const { items, activeId, onChange, variant = 'underline', separator, autoFocus, ...rest } = props;
4
6
  const focus = useFocus({ autoFocus });
@@ -19,12 +21,20 @@ export const Tabs = defineComponent('Tabs', (props) => {
19
21
  key: item.id,
20
22
  role: 'tab',
21
23
  label: item.label,
24
+ styleAs: TABS,
25
+ // Carried so the theme can tell a filled tab from an unfilled one: a
26
+ // solid tab is `Tabs.solid.selected`, an underline one is not filled
27
+ // at all. See `Tabs` in the built-in themes.
28
+ variant,
29
+ // A tab is open, not selected, and it says so with one state. There is
30
+ // no second name for it because there is nothing to dim: the document
31
+ // a tab names is open whether or not the strip has the keyboard, and
32
+ // dimming the tab on losing focus would claim none is.
22
33
  selected: active,
23
34
  direction: 'row',
24
35
  gap: 1,
25
36
  padding: variant === 'solid' ? [0, 1] : 0,
26
- bg: variant === 'solid' && active ? 'selected' : undefined,
27
- fg: item.disabled ? 'disabled' : active ? (variant === 'solid' ? 'inverted' : 'accent') : 'muted',
37
+ fg: item.disabled ? 'disabled' : active ? (variant === 'solid' ? undefined : 'accent') : 'muted',
28
38
  bold: active,
29
39
  underline: variant === 'underline' && active,
30
40
  onClick: () => { if (!item.disabled)
@@ -1 +1 @@
1
- {"version":3,"file":"command-palette.d.ts","sourceRoot":"","sources":["../../src/overlay/command-palette.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAa,MAAM,cAAc,CAAC;AAiB/F,MAAM,WAAW,mBAAoB,SAAQ,QAAQ;IACnD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,iBAAiB,EAAE,GAAG,CAAC,MAAM,iBAAiB,EAAE,CAAC,CAAC;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,KAAK,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAClC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAyBD,eAAO,MAAM,cAAc,qEAqczB,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,iBAAiB,EAC1B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACtC,OAAO,GAAG,SAAS,CAKrB;AAyCD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAehG"}
1
+ {"version":3,"file":"command-palette.d.ts","sourceRoot":"","sources":["../../src/overlay/command-palette.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAa,MAAM,cAAc,CAAC;AAkB/F,MAAM,WAAW,mBAAoB,SAAQ,QAAQ;IACnD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,iBAAiB,EAAE,GAAG,CAAC,MAAM,iBAAiB,EAAE,CAAC,CAAC;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iEAAiE;IACjE,KAAK,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACzD,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,uEAAuE;IACvE,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAClC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAyBD,eAAO,MAAM,cAAc,qEAsezB,CAAC;AAEH;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,iBAAiB,EAC1B,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACtC,OAAO,GAAG,SAAS,CAKrB;AA2DD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,iBAAiB,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAehG"}
@@ -1,9 +1,11 @@
1
- import { defineComponent, h, stringWidth, useEffect, useFocusScope, useInput, useRuntime, useState, useTheme, } from '@textui/core';
1
+ import { defineComponent, h, stringWidth, useEffect, useFocusScope, useI18n, useInput, useRuntime, useState, useTheme, } from '@textui/core';
2
2
  import { TextInput } from '../control/index.js';
3
3
  import { Menu } from '../navigation/index.js';
4
4
  import { hint } from './shared.js';
5
5
  export const CommandPalette = defineComponent('CommandPalette', (props) => {
6
6
  const theme = useTheme();
7
+ const i18n = useI18n();
8
+ const ellipsis = theme.glyphs.ellipsis;
7
9
  const runtime = useRuntime();
8
10
  const { commands, placeholder, onRun, onClose, execute = true, grouped = true, visibleRows = 8, width, maxWidth = 60, openAt, descriptions = 'inline', ...rest } = props;
9
11
  const [query, setQuery] = useState('');
@@ -28,7 +30,9 @@ export const CommandPalette = defineComponent('CommandPalette', (props) => {
28
30
  const app = runtime.app();
29
31
  const given = typeof commands === 'function' ? commands() : commands;
30
32
  const all = given ?? app?.commands.list({ slot: 'palette', enabledOnly: true }) ?? [];
31
- const matches = pending ? [] : filterCommands(all, query);
33
+ const matches = pending
34
+ ? []
35
+ : grouped && query.trim() === '' ? byCategory(all) : filterCommands(all, query);
32
36
  const offered = pending ? filterChoices(choices, query) : [];
33
37
  const rows = pending ? offered.map((choice) => choice.value) : matches.map((c) => c.id);
34
38
  const index = Math.max(0, Math.min(highlight, rows.length - 1));
@@ -42,7 +46,9 @@ export const CommandPalette = defineComponent('CommandPalette', (props) => {
42
46
  // the only thing the palette itself knows about a value.
43
47
  ...(choice.description
44
48
  ? { description: choice.description }
45
- : pending.arg.default === choice.value ? { description: 'default' } : {}),
49
+ : pending.arg.default === choice.value
50
+ ? { description: i18n.t('textui.palette.default', undefined, 'default') }
51
+ : {}),
46
52
  }))
47
53
  // One row, saying which kind of nothing this is. A disabled item rather
48
54
  // than no items: the panel keeps its height, so the answer arriving does
@@ -50,8 +56,10 @@ export const CommandPalette = defineComponent('CommandPalette', (props) => {
50
56
  : [{
51
57
  id: '',
52
58
  label: asking
53
- ? `Asking${theme.glyphs.ellipsis}`
54
- : (query === '' ? 'Nothing to choose' : 'No match'),
59
+ ? i18n.t('textui.palette.asking', { ellipsis }, 'Asking{ellipsis}')
60
+ : (query === ''
61
+ ? i18n.t('textui.palette.nothingToChoose', undefined, 'Nothing to choose')
62
+ : i18n.t('textui.palette.noMatch', undefined, 'No match')),
55
63
  disabled: true,
56
64
  }])
57
65
  : matches.map((command, i) => ({
@@ -304,7 +312,8 @@ export const CommandPalette = defineComponent('CommandPalette', (props) => {
304
312
  return false;
305
313
  }, { global: true });
306
314
  const highlighted = pending ? undefined : matches[index];
307
- const move = `${theme.glyphs.arrowUp}${theme.glyphs.arrowDown} move`;
315
+ const move = i18n.t('textui.palette.hint.move', { arrows: `${theme.glyphs.arrowUp}${theme.glyphs.arrowDown}` }, '{arrows} move');
316
+ const escBack = i18n.t('textui.palette.hint.back', undefined, 'esc back');
308
317
  // What the highlighted row is, in full.
309
318
  //
310
319
  // The rows themselves have to fit, so a choice's own sentence is truncated
@@ -316,7 +325,8 @@ export const CommandPalette = defineComponent('CommandPalette', (props) => {
316
325
  const chosen = pending ? offered[index] : undefined;
317
326
  const detail = pending
318
327
  ? chosen?.description
319
- ?? pending.arg.description ?? `${pending.command.title} needs a ${pending.arg.name}`
328
+ ?? pending.arg.description
329
+ ?? i18n.t('textui.palette.needs', { command: pending.command.title, arg: pending.arg.name }, '{command} needs a {arg}')
320
330
  : highlighted?.description ?? highlighted?.id ?? '';
321
331
  /*
322
332
  * How wide the panel wants to be.
@@ -341,7 +351,7 @@ export const CommandPalette = defineComponent('CommandPalette', (props) => {
341
351
  : []));
342
352
  return h('box', {
343
353
  role: 'dialog',
344
- label: 'Commands',
354
+ label: i18n.t('textui.palette.label', undefined, 'Commands'),
345
355
  border: theme.border,
346
356
  bg: 'overlay',
347
357
  // A stated width is a width. Left off, it fits what it holds.
@@ -357,8 +367,8 @@ export const CommandPalette = defineComponent('CommandPalette', (props) => {
357
367
  // where you are; "commands › id" is what the parameter happens to be
358
368
  // called, which is the author's business rather than the reader's.
359
369
  title: pending
360
- ? ` commands ${theme.glyphs.breadcrumb} ${pending.command.title} `
361
- : ' commands ',
370
+ ? ` ${i18n.t('textui.palette.title', undefined, 'commands')} ${theme.glyphs.breadcrumb} ${pending.command.title} `
371
+ : ` ${i18n.t('textui.palette.title', undefined, 'commands')} `,
362
372
  ...rest,
363
373
  }, h(TextInput, {
364
374
  value: query,
@@ -396,8 +406,8 @@ export const CommandPalette = defineComponent('CommandPalette', (props) => {
396
406
  ? pending.arg.description ?? `${pending.command.title}${theme.glyphs.ellipsis}`
397
407
  : offered.some((choice) => choice.description) && pending.arg.description
398
408
  ? pending.arg.description
399
- : `Choose ${pending.command.title.toLowerCase()}${theme.glyphs.ellipsis}`)
400
- : (placeholder ?? `Type a command${theme.glyphs.ellipsis}`),
409
+ : i18n.t('textui.palette.choose', { command: pending.command.title.toLowerCase(), ellipsis }, 'Choose {command}{ellipsis}'))
410
+ : (placeholder ?? i18n.t('textui.palette.placeholder', { ellipsis }, 'Type a command{ellipsis}')),
401
411
  search: true,
402
412
  autoFocus: true,
403
413
  border: 'none',
@@ -421,11 +431,22 @@ export const CommandPalette = defineComponent('CommandPalette', (props) => {
421
431
  h('box', { direction: 'row', gap: 1, align: 'start' }, h('text', { content: detail, fg: 'muted', flex: 1, wrap: 'word' }), h('text', { content: `${rows.length}`, fg: 'subtle' })), h('box', { direction: 'row', gap: 1 }, h('text', {
422
432
  content: pending
423
433
  ? (pending.arg.choices === undefined
424
- ? hint(theme, ['type it', 'enter confirm', 'esc back'])
434
+ ? hint(theme, [
435
+ i18n.t('textui.palette.hint.type', undefined, 'type it'),
436
+ i18n.t('textui.palette.hint.confirm', undefined, 'enter confirm'),
437
+ escBack,
438
+ ])
425
439
  // Nothing to choose is nothing to press enter on, and offering it
426
440
  // is how a panel reads as broken rather than as empty.
427
- : hint(theme, rows.length > 0 ? [move, 'enter choose', 'esc back'] : ['esc back']))
428
- : hint(theme, [move, 'enter run', `${theme.glyphs.chevronRight} sub-items`, 'esc close']),
441
+ : hint(theme, rows.length > 0
442
+ ? [move, i18n.t('textui.palette.hint.choose', undefined, 'enter choose'), escBack]
443
+ : [escBack]))
444
+ : hint(theme, [
445
+ move,
446
+ i18n.t('textui.palette.hint.run', undefined, 'enter run'),
447
+ i18n.t('textui.palette.hint.subItems', { glyph: theme.glyphs.chevronRight }, '{glyph} sub-items'),
448
+ i18n.t('textui.palette.hint.close', undefined, 'esc close'),
449
+ ]),
429
450
  fg: 'subtle',
430
451
  truncate: 'end',
431
452
  })));
@@ -485,6 +506,25 @@ function filterChoices(choices, query) {
485
506
  return choices.filter((choice) => `${choice.label ?? ''} ${choice.value} ${choice.description ?? ''}`
486
507
  .toLowerCase().includes(q));
487
508
  }
509
+ /**
510
+ * Each category's commands together, the categories in the order they first
511
+ * appear and the commands in the order they came.
512
+ *
513
+ * Registration order is whatever order the code happened to run in, so a
514
+ * category registered in two places would be two groups with the same name
515
+ * over them.
516
+ */
517
+ function byCategory(commands) {
518
+ const groups = new Map();
519
+ for (const command of commands) {
520
+ const group = groups.get(command.category);
521
+ if (group)
522
+ group.push(command);
523
+ else
524
+ groups.set(command.category, [command]);
525
+ }
526
+ return [...groups.values()].flat();
527
+ }
488
528
  export function filterCommands(commands, query) {
489
529
  const q = query.trim().toLowerCase();
490
530
  if (q === '')
@@ -13,4 +13,15 @@ export interface DialogProps extends BoxProps {
13
13
  width?: number;
14
14
  }
15
15
  export declare const Dialog: (props: DialogProps) => import("@textui/core").RenderOutput;
16
+ export interface ConfirmDialogProps extends BoxProps {
17
+ title?: string;
18
+ message: string;
19
+ confirmLabel?: string;
20
+ cancelLabel?: string;
21
+ tone?: SemanticVariant;
22
+ onConfirm?(): void;
23
+ onCancel?(): void;
24
+ }
25
+ /** Two-button dialog behind the `confirm` helper. */
26
+ export declare const ConfirmDialog: (props: ConfirmDialogProps) => import("@textui/core").RenderOutput;
16
27
  //# sourceMappingURL=dialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/overlay/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAI9D,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,eAAe,CAAC;QAAC,OAAO,CAAC,IAAI,IAAI,CAAA;KAAE,EAAE,CAAC;IACpF,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,MAAM,6DAmDjB,CAAC"}
1
+ {"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../src/overlay/dialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAI9D,MAAM,WAAW,WAAY,SAAQ,QAAQ;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iEAAiE;IACjE,OAAO,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,eAAe,CAAC;QAAC,OAAO,CAAC,IAAI,IAAI,CAAA;KAAE,EAAE,CAAC;IACpF,OAAO,CAAC,IAAI,IAAI,CAAC;IACjB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,MAAM,6DAmDjB,CAAC;AAEH,MAAM,WAAW,kBAAmB,SAAQ,QAAQ;IAClD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,SAAS,CAAC,IAAI,IAAI,CAAC;IACnB,QAAQ,CAAC,IAAI,IAAI,CAAC;CACnB;AAED,qDAAqD;AACrD,eAAO,MAAM,aAAa,oEAuBxB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { defineComponent, h, useFocusScope, useInput, useTheme } from '@textui/core';
1
+ import { defineComponent, h, useFocusScope, useI18n, useInput, useTheme } from '@textui/core';
2
2
  import { Button } from '../control/index.js';
3
3
  export const Dialog = defineComponent('Dialog', (props) => {
4
4
  const theme = useTheme();
@@ -42,3 +42,26 @@ export const Dialog = defineComponent('Dialog', (props) => {
42
42
  })))
43
43
  : null);
44
44
  });
45
+ /** Two-button dialog behind the `confirm` helper. */
46
+ export const ConfirmDialog = defineComponent('ConfirmDialog', (props) => {
47
+ const i18n = useI18n();
48
+ const { title, message, confirmLabel, cancelLabel, tone, onConfirm, onCancel, ...rest } = props;
49
+ return h(Dialog, {
50
+ title: title ?? i18n.t('textui.confirmDialog.title', undefined, 'Confirm'),
51
+ width: 50,
52
+ actions: [
53
+ {
54
+ id: 'confirm',
55
+ label: confirmLabel ?? i18n.t('textui.confirmDialog.confirm', undefined, 'Confirm'),
56
+ tone: tone ?? 'primary',
57
+ onPress: onConfirm,
58
+ },
59
+ {
60
+ id: 'cancel',
61
+ label: cancelLabel ?? i18n.t('textui.confirmDialog.cancel', undefined, 'Cancel'),
62
+ onPress: onCancel,
63
+ },
64
+ ],
65
+ ...rest,
66
+ }, h('text', { content: message, wrap: 'word' }));
67
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/overlay/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,UAAU,EACV,UAAU,EACV,aAAa,EACb,eAAe,EACf,SAAS,EACV,MAAM,cAAc,CAAC;AAMtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKtD;;;;;;GAMG;AACH,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAE7B,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE;IAAE,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,CAAA;CAAE,EACxD,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CAwClB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,MAAM,CACpB,MAAM,EAAE;IAAE,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,CAAA;CAAE,EACxD,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6BxB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA8BjF;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAID,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,GAAG,UAAU,CAQzE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,aAAa,CAO7E;AAED,eAAO,MAAM,kBAAkB,EAAE,mBAAmB,EASnD,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/overlay/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,mBAAmB,EACnB,UAAU,EACV,UAAU,EACV,aAAa,EACb,eAAe,EACf,SAAS,EACV,MAAM,cAAc,CAAC;AAMtB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAKtD;;;;;;GAMG;AACH,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAE7B,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,eAAe,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,OAAO,CACrB,MAAM,EAAE;IAAE,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,CAAA;CAAE,EACxD,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,OAAO,CAAC,CA+BlB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,MAAM,CACpB,MAAM,EAAE;IAAE,IAAI,CAAC,KAAK,EAAE,UAAU,GAAG;QAAE,OAAO,IAAI,IAAI,CAAA;KAAE,CAAA;CAAE,EACxD,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6BxB;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA8BjF;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,EAAE,CAAC,EAAE,MAAM,CAAC;CACb;AAID,wBAAgB,MAAM,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,GAAG,UAAU,CAQzE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,GAAG,aAAa,CAO7E;AAED,eAAO,MAAM,kBAAkB,EAAE,mBAAmB,EAUnD,CAAC"}
@@ -1,5 +1,5 @@
1
1
  import { CommandPalette } from './command-palette.js';
2
- import { Dialog } from './dialog.js';
2
+ import { ConfirmDialog, Dialog } from './dialog.js';
3
3
  import { LayerScope } from './layer-scope.js';
4
4
  import { PathPicker } from './path-picker.js';
5
5
  import { PromptDialog } from './prompt-dialog.js';
@@ -45,23 +45,14 @@ export function confirm(layers, options) {
45
45
  dismissOnEscape: true,
46
46
  onClose: () => finish(false),
47
47
  node: {
48
- component: 'Dialog',
49
- title: options.title ?? 'Confirm',
50
- width: 50,
51
- children: { component: 'text', content: options.message, wrap: 'word' },
52
- actions: [
53
- {
54
- id: 'confirm',
55
- label: options.confirmLabel ?? 'Confirm',
56
- tone: options.tone ?? 'primary',
57
- onPress: () => finish(true),
58
- },
59
- {
60
- id: 'cancel',
61
- label: options.cancelLabel ?? 'Cancel',
62
- onPress: () => finish(false),
63
- },
64
- ],
48
+ component: 'ConfirmDialog',
49
+ title: options.title,
50
+ message: options.message,
51
+ confirmLabel: options.confirmLabel,
52
+ cancelLabel: options.cancelLabel,
53
+ tone: options.tone,
54
+ onConfirm: { handler: () => finish(true) },
55
+ onCancel: { handler: () => finish(false) },
65
56
  },
66
57
  });
67
58
  });
@@ -85,7 +76,7 @@ export function prompt(layers, options) {
85
76
  onClose: () => finish(null),
86
77
  node: {
87
78
  component: 'PromptDialog',
88
- title: options.title ?? 'Input',
79
+ title: options.title,
89
80
  message: options.message,
90
81
  placeholder: options.placeholder,
91
82
  initialValue: options.initialValue,
@@ -147,6 +138,7 @@ export function toastPosition(anchor) {
147
138
  }
148
139
  export const OVERLAY_COMPONENTS = [
149
140
  { component: 'Dialog', category: 'overlay', renderer: { kind: 'function', render: Dialog }, role: 'dialog', description: 'Modal box with actions; traps focus and restores it.' },
141
+ { component: 'ConfirmDialog', category: 'overlay', renderer: { kind: 'function', render: ConfirmDialog }, role: 'dialog', description: 'Two-button dialog behind the `confirm` helper.' },
150
142
  { component: 'PromptDialog', category: 'overlay', renderer: { kind: 'function', render: PromptDialog }, role: 'dialog', description: 'One-field dialog behind the `prompt` helper.' },
151
143
  { component: 'PathPicker', category: 'overlay', renderer: { kind: 'function', render: PathPicker }, role: 'dialog', description: 'Walk the resource tree and pick a file or a folder.' },
152
144
  { component: 'Tooltip', category: 'overlay', renderer: { kind: 'function', render: Tooltip }, role: 'tooltip', description: 'Small anchored hint.' },
@@ -1 +1 @@
1
- {"version":3,"file":"path-picker.d.ts","sourceRoot":"","sources":["../../src/overlay/path-picker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAgB7C,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,IAAI,IAAI,CAAC;CACnB;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQnD;AAED,eAAO,MAAM,UAAU,iEAiLrB,CAAC"}
1
+ {"version":3,"file":"path-picker.d.ts","sourceRoot":"","sources":["../../src/overlay/path-picker.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAiB7C,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,IAAI,IAAI,CAAC;CACnB;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQnD;AAED,eAAO,MAAM,UAAU,iEA6LrB,CAAC"}
@@ -1,4 +1,4 @@
1
- import { defineComponent, h, nameOf, useEffect, useInput, useRuntime, useState, useTheme, } from '@textui/core';
1
+ import { defineComponent, h, nameOf, useEffect, useI18n, useInput, useRuntime, useState, useTheme, } from '@textui/core';
2
2
  import { TextInput } from '../control/index.js';
3
3
  import { Menu } from '../navigation/index.js';
4
4
  import { hint } from './shared.js';
@@ -17,6 +17,8 @@ export function parentOf(uri) {
17
17
  export const PathPicker = defineComponent('PathPicker', (props) => {
18
18
  const { start, wants = 'file', title, placeholder, visibleRows = 10, width = 60, onPick, onCancel, ...rest } = props;
19
19
  const theme = useTheme();
20
+ const i18n = useI18n();
21
+ const ellipsis = theme.glyphs.ellipsis;
20
22
  const runtime = useRuntime();
21
23
  const app = runtime.app();
22
24
  const [at, setAt] = useState(start);
@@ -63,7 +65,7 @@ export const PathPicker = defineComponent('PathPicker', (props) => {
63
65
  // child to press enter on and a hidden chord for it is a chord nobody
64
66
  // finds. It is first, since it is the answer most often wanted.
65
67
  ...(wants === 'directory'
66
- ? [{ id: '.', label: 'Use this folder', icon: theme.glyphs.check }]
68
+ ? [{ id: '.', label: i18n.t('textui.pathPicker.useFolder', undefined, 'Use this folder'), icon: theme.glyphs.check }]
67
69
  : []),
68
70
  ...(parent !== null ? [{ id: '..', label: '..', icon: theme.glyphs.chevronUp }] : []),
69
71
  ...shown.map((e) => ({
@@ -130,16 +132,18 @@ export const PathPicker = defineComponent('PathPicker', (props) => {
130
132
  }
131
133
  return false;
132
134
  }, { global: true });
133
- const move = `${theme.glyphs.arrowUp}${theme.glyphs.arrowDown} move`;
135
+ const move = i18n.t('textui.pathPicker.hint.move', { arrows: `${theme.glyphs.arrowUp}${theme.glyphs.arrowDown}` }, '{arrows} move');
134
136
  return h('box', {
135
137
  role: 'dialog',
136
- label: title ?? 'Choose',
138
+ label: title ?? i18n.t('textui.pathPicker.label', undefined, 'Choose'),
137
139
  border: theme.border,
138
140
  bg: 'overlay',
139
141
  width,
140
142
  direction: 'column',
141
143
  ...(theme.border === 'none' ? { padding: { left: 1, right: 1 } } : {}),
142
- title: ` ${title ?? (wants === 'directory' ? 'choose a folder' : 'choose a file')} `,
144
+ title: ` ${title ?? (wants === 'directory'
145
+ ? i18n.t('textui.pathPicker.titleFolder', undefined, 'choose a folder')
146
+ : i18n.t('textui.pathPicker.titleFile', undefined, 'choose a file'))} `,
143
147
  ...rest,
144
148
  },
145
149
  // Where you are. A column of bare names with no header is a list you can
@@ -161,7 +165,7 @@ export const PathPicker = defineComponent('PathPicker', (props) => {
161
165
  */
162
166
  onEdge: (edge) => { if (edge === 'start')
163
167
  up(); },
164
- placeholder: placeholder ?? `Filter${theme.glyphs.ellipsis}`,
168
+ placeholder: placeholder ?? i18n.t('textui.pathPicker.placeholder', { ellipsis }, 'Filter{ellipsis}'),
165
169
  search: true,
166
170
  autoFocus: true,
167
171
  border: 'none',
@@ -183,16 +187,20 @@ export const PathPicker = defineComponent('PathPicker', (props) => {
183
187
  shown.length === 0
184
188
  ? h('text', {
185
189
  content: loading
186
- ? `Reading${theme.glyphs.ellipsis}`
187
- : (q === '' ? 'Nothing here.' : 'Nothing matches.'),
190
+ ? i18n.t('textui.pathPicker.reading', { ellipsis }, 'Reading{ellipsis}')
191
+ : (q === ''
192
+ ? i18n.t('textui.pathPicker.empty', undefined, 'Nothing here.')
193
+ : i18n.t('textui.pathPicker.noMatch', undefined, 'Nothing matches.')),
188
194
  fg: 'muted',
189
195
  })
190
196
  : null, h('box', { height: 1, fill: theme.borderChars().top, fg: 'borderSubtle' }), h('text', {
191
197
  content: hint(theme, [
192
198
  move,
193
- wants === 'directory' ? 'enter open' : 'enter choose',
194
- `${theme.glyphs.chevronLeft} up`,
195
- 'esc cancel',
199
+ wants === 'directory'
200
+ ? i18n.t('textui.pathPicker.hint.open', undefined, 'enter open')
201
+ : i18n.t('textui.pathPicker.hint.choose', undefined, 'enter choose'),
202
+ i18n.t('textui.pathPicker.hint.up', { glyph: theme.glyphs.chevronLeft }, '{glyph} up'),
203
+ i18n.t('textui.pathPicker.hint.cancel', undefined, 'esc cancel'),
196
204
  ]),
197
205
  fg: 'subtle',
198
206
  truncate: 'end',
@@ -1 +1 @@
1
- {"version":3,"file":"prompt-dialog.d.ts","sourceRoot":"","sources":["../../src/overlay/prompt-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAK7C,MAAM,WAAW,iBAAkB,SAAQ,QAAQ;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,IAAI,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,YAAY,mEA6BvB,CAAC"}
1
+ {"version":3,"file":"prompt-dialog.d.ts","sourceRoot":"","sources":["../../src/overlay/prompt-dialog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAK7C,MAAM,WAAW,iBAAkB,SAAQ,QAAQ;IACjD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,IAAI,IAAI,CAAC;CACnB;AAED,eAAO,MAAM,YAAY,mEA8BvB,CAAC"}
@@ -1,16 +1,17 @@
1
- import { defineComponent, h, useState } from '@textui/core';
1
+ import { defineComponent, h, useI18n, useState } from '@textui/core';
2
2
  import { TextInput } from '../control/index.js';
3
3
  import { Dialog } from './dialog.js';
4
4
  export const PromptDialog = defineComponent('PromptDialog', (props) => {
5
5
  const { title, message, placeholder, initialValue = '', mask, onSubmit, onCancel, ...rest } = props;
6
+ const i18n = useI18n();
6
7
  const [value, setValue] = useState(initialValue);
7
8
  return h(Dialog, {
8
- title,
9
+ title: title ?? i18n.t('textui.promptDialog.title', undefined, 'Input'),
9
10
  width: 50,
10
11
  onClose: onCancel,
11
12
  actions: [
12
- { id: 'ok', label: 'OK', tone: 'primary', onPress: () => onSubmit?.(value) },
13
- { id: 'cancel', label: 'Cancel', onPress: onCancel },
13
+ { id: 'ok', label: i18n.t('textui.promptDialog.ok', undefined, 'OK'), tone: 'primary', onPress: () => onSubmit?.(value) },
14
+ { id: 'cancel', label: i18n.t('textui.promptDialog.cancel', undefined, 'Cancel'), onPress: onCancel },
14
15
  ],
15
16
  ...rest,
16
17
  }, message ? h('text', { content: message, wrap: 'word' }) : null, h(TextInput, {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/panel/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,iBAAiB,EACjB,aAAa,EAEb,SAAS,EACV,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAalE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,cAAc,qBAAqB,CAAC;AAEpC,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEvD;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAEpF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAE/D;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAExE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAElF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE9E;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE1F;AAED,iEAAiE;AACjE,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,aAAa,EACpB,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,IAAI,CAMN;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,IAAI,WAAW,GAAG,IAAI,CAE7C;AAQD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,QAAQ,EAAE,CAAC,GACV,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CA0BlC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAUxD;AAgDD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,GAAG,iBAAiB,EAAE,CAsFjE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/panel/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EAEX,iBAAiB,EACjB,aAAa,EAEb,SAAS,EACV,MAAM,cAAc,CAAC;AAEtB,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAalE;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,cAAc,qBAAqB,CAAC;AAEpC,wBAAgB,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEvD;AAED,6EAA6E;AAC7E,wBAAgB,UAAU,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAEpF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,GAAG,IAAI,CAE/D;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAExE;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,CAElF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAE9E;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAE1F;AAED,iEAAiE;AACjE,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,aAAa,EACpB,EAAE,EAAE,MAAM,EACV,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,GAAG,IAAI,GACtB,IAAI,CAMN;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,IAAI,WAAW,GAAG,IAAI,CAE7C;AAQD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7D,QAAQ,EAAE,CAAC,GACV,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CA0BlC;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAUxD;AAgDD;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,GAAG,iBAAiB,EAAE,CAwFjE"}
@@ -182,18 +182,19 @@ export function panelCommands(app) {
182
182
  * to draw it.
183
183
  */
184
184
  const targetUri = (args, id) => args.uri ?? (id === null ? null : panelUri(app.store, id));
185
+ const category = app.i18n.t('textui.panel.category', undefined, 'View');
185
186
  return [
186
187
  {
187
188
  id: 'panel.openWith',
188
- title: 'Open With…',
189
- category: 'View',
189
+ title: app.i18n.t('textui.panel.openWith', undefined, 'Open With…'),
190
+ category,
190
191
  slots: ['palette'],
191
192
  when: PANEL_PATH,
192
193
  args: [{
193
194
  name: 'renderer',
194
195
  type: 'string',
195
196
  required: true,
196
- description: 'How to show this resource',
197
+ description: app.i18n.t('textui.panel.renderer', undefined, 'How to show this resource'),
197
198
  choices: async () => {
198
199
  const id = activePanel(app.store);
199
200
  return (await choicesFor(app, id === null ? null : panelUri(app.store, id)))
@@ -210,8 +211,8 @@ export function panelCommands(app) {
210
211
  },
211
212
  {
212
213
  id: 'panel.nextRenderer',
213
- title: 'Next View',
214
- category: 'View',
214
+ title: app.i18n.t('textui.panel.nextView', undefined, 'Next View'),
215
+ category,
215
216
  slots: ['palette'],
216
217
  when: PANEL_PATH,
217
218
  run: async (args, ctx) => {
@@ -230,8 +231,8 @@ export function panelCommands(app) {
230
231
  },
231
232
  {
232
233
  id: 'panel.toggleEdit',
233
- title: 'Edit / View',
234
- category: 'View',
234
+ title: app.i18n.t('textui.panel.toggleEdit', undefined, 'Edit / View'),
235
+ category,
235
236
  slots: ['palette'],
236
237
  when: PANEL_PATH,
237
238
  run: async (args, ctx) => {
@@ -1 +1 @@
1
- {"version":3,"file":"resource-panel.d.ts","sourceRoot":"","sources":["../../src/panel/resource-panel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,mBAAmB,EAEnB,QAAQ,EACR,0BAA0B,EAC3B,MAAM,cAAc,CAAC;AAetB,sCAAsC;AACtC,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAEzC,sCAAsC;AACtC,eAAO,MAAM,UAAU,EAAmB,WAAW,CAAC;AAEtD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEjD;AAED,mDAAmD;AACnD,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAElE;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEpD;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEtD;AAED,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,0BAA0B,EAAE,GACtC,0BAA0B,GAAG,IAAI,CAEnC;AAID,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAID,MAAM,WAAW,kBAAmB,SAAQ,QAAQ;IAClD;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,oEAsJxB,CAAC;AAEH,eAAO,MAAM,gBAAgB,EAAE,mBAAmB,EAOjD,CAAC"}
1
+ {"version":3,"file":"resource-panel.d.ts","sourceRoot":"","sources":["../../src/panel/resource-panel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,QAAQ,EACR,mBAAmB,EAEnB,QAAQ,EACR,0BAA0B,EAC3B,MAAM,cAAc,CAAC;AAgBtB,sCAAsC;AACtC,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAEzC,sCAAsC;AACtC,eAAO,MAAM,UAAU,EAAmB,WAAW,CAAC;AAEtD,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEjD;AAED,mDAAmD;AACnD,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAElE;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEpD;AAED,6EAA6E;AAC7E,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEzD;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,WAAW,CAEtD;AAED,MAAM,WAAW,SAAS;IACxB,wDAAwD;IACxD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAE1D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,SAAS,EAAE,0BAA0B,EAAE,GACtC,0BAA0B,GAAG,IAAI,CAEnC;AAID,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAID,MAAM,WAAW,kBAAmB,SAAQ,QAAQ;IAClD;;;;;;OAMG;IACH,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,8EAA8E;IAC9E,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,kEAAkE;IAClE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,qDAAqD;IACrD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,aAAa,oEA0JxB,CAAC;AAEH,eAAO,MAAM,gBAAgB,EAAE,mBAAmB,EAOjD,CAAC"}