@moyarich/console-addon-selection 0.0.0-stage → 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 +38 -2
- package/dist/components/SelectedMessageIndicator/SelectedMessageIndicator.d.cts +6 -0
- package/dist/components/SelectedMessageIndicator/SelectedMessageIndicator.d.ts +6 -0
- package/dist/index.cjs +244 -0
- package/dist/index.d.cts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +244 -0
- package/dist/locales/en.json +6 -0
- package/dist/locales/es.json +6 -0
- package/dist/locales/fr.json +6 -0
- package/dist/locales/pt.json +6 -0
- package/dist/localization.d.cts +4 -0
- package/dist/localization.d.ts +4 -0
- package/package.json +62 -4
package/README.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @moyarich/console-addon-selection
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Select Console messages. Select message IDs individually or in visible ranges, with optional message actions and decorations.
|
|
4
|
+
|
|
5
|
+
[Documentation and live examples](https://moyarich.github.io/console/)
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @moyarich/console @moyarich/console-addon-selection react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Configure the `@moyarich` scope and authenticate with GitHub Packages as described in the [installation guide](../../../README.md#installation).
|
|
14
|
+
|
|
15
|
+
Required peer dependencies: `@moyarich/console-core@^0.2.0`, `react@>=18`.
|
|
16
|
+
|
|
17
|
+
## Quick start
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { Console } from "@moyarich/console";
|
|
21
|
+
import { createConsoleSelectionAddon } from "@moyarich/console-addon-selection";
|
|
22
|
+
|
|
23
|
+
const addons = [createConsoleSelectionAddon()];
|
|
24
|
+
|
|
25
|
+
// Pass your application's structured messages to Console.
|
|
26
|
+
<Console messages={messages} addons={addons} />;
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The addon is optional and can be combined with other Console addons. The host application remains responsible for supplying and retaining messages.
|
|
30
|
+
|
|
31
|
+
## Learn more
|
|
32
|
+
|
|
33
|
+
Explore [runnable package examples](./examples) and the [Console documentation](https://moyarich.github.io/console/) for available settings and integration patterns.
|
|
34
|
+
|
|
35
|
+
Review the [changelog](./CHANGELOG.md) for changes by version and [package metadata](./package.json) for dependency requirements.
|
|
36
|
+
|
|
37
|
+
## License
|
|
38
|
+
|
|
39
|
+
MIT
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type AddonTranslations } from "../../localization.cjs";
|
|
2
|
+
/** Default selection indicator. No stylesheet or addon runtime required. */
|
|
3
|
+
export declare function SelectedMessageIndicator({ locale, translations, }?: {
|
|
4
|
+
locale?: string;
|
|
5
|
+
translations?: AddonTranslations;
|
|
6
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type AddonTranslations } from "../../localization.js";
|
|
2
|
+
/** Default selection indicator. No stylesheet or addon runtime required. */
|
|
3
|
+
export declare function SelectedMessageIndicator({ locale, translations, }?: {
|
|
4
|
+
locale?: string;
|
|
5
|
+
translations?: AddonTranslations;
|
|
6
|
+
}): import("react").JSX.Element;
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
+
const consoleCore = require("@moyarich/console-core");
|
|
5
|
+
const selectedMessage$3 = "Selected message";
|
|
6
|
+
const selected$3 = "Selected";
|
|
7
|
+
const toggleSelection$3 = "Toggle selection";
|
|
8
|
+
const toggleMessageSelection$3 = "Toggle message selection";
|
|
9
|
+
const en = {
|
|
10
|
+
selectedMessage: selectedMessage$3,
|
|
11
|
+
selected: selected$3,
|
|
12
|
+
toggleSelection: toggleSelection$3,
|
|
13
|
+
toggleMessageSelection: toggleMessageSelection$3
|
|
14
|
+
};
|
|
15
|
+
const selectedMessage$2 = "Mensaje seleccionado";
|
|
16
|
+
const selected$2 = "Seleccionado";
|
|
17
|
+
const toggleSelection$2 = "Alternar selección";
|
|
18
|
+
const toggleMessageSelection$2 = "Alternar selección del mensaje";
|
|
19
|
+
const es = {
|
|
20
|
+
selectedMessage: selectedMessage$2,
|
|
21
|
+
selected: selected$2,
|
|
22
|
+
toggleSelection: toggleSelection$2,
|
|
23
|
+
toggleMessageSelection: toggleMessageSelection$2
|
|
24
|
+
};
|
|
25
|
+
const selectedMessage$1 = "Message sélectionné";
|
|
26
|
+
const selected$1 = "Sélectionné";
|
|
27
|
+
const toggleSelection$1 = "Activer/désactiver la sélection";
|
|
28
|
+
const toggleMessageSelection$1 = "Activer/désactiver la sélection du message";
|
|
29
|
+
const fr = {
|
|
30
|
+
selectedMessage: selectedMessage$1,
|
|
31
|
+
selected: selected$1,
|
|
32
|
+
toggleSelection: toggleSelection$1,
|
|
33
|
+
toggleMessageSelection: toggleMessageSelection$1
|
|
34
|
+
};
|
|
35
|
+
const selectedMessage = "Mensagem selecionada";
|
|
36
|
+
const selected = "Selecionado";
|
|
37
|
+
const toggleSelection = "Alternar seleção";
|
|
38
|
+
const toggleMessageSelection = "Alternar seleção da mensagem";
|
|
39
|
+
const pt = {
|
|
40
|
+
selectedMessage,
|
|
41
|
+
selected,
|
|
42
|
+
toggleSelection,
|
|
43
|
+
toggleMessageSelection
|
|
44
|
+
};
|
|
45
|
+
const dictionaries = { en, es, fr, pt };
|
|
46
|
+
function resolveAddonMessages(locale = "en", overrides) {
|
|
47
|
+
const tag = locale.replace(/_/g, "-").toLowerCase();
|
|
48
|
+
return {
|
|
49
|
+
...en,
|
|
50
|
+
...dictionaries[tag] ?? dictionaries[tag.split("-")[0]] ?? {},
|
|
51
|
+
...overrides
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function SelectedMessageIndicator({
|
|
55
|
+
locale = "en",
|
|
56
|
+
translations
|
|
57
|
+
} = {}) {
|
|
58
|
+
const t = resolveAddonMessages(locale, translations);
|
|
59
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
60
|
+
"span",
|
|
61
|
+
{
|
|
62
|
+
"aria-label": t.selectedMessage,
|
|
63
|
+
title: t.selected,
|
|
64
|
+
style: { fontSize: 12, lineHeight: 1 },
|
|
65
|
+
children: "●"
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
const CONSOLE_SELECTION_ADDON_ID = "@moyarich/console-addon-selection";
|
|
70
|
+
const consoleSelectionService = consoleCore.createConsoleServiceToken(
|
|
71
|
+
`${CONSOLE_SELECTION_ADDON_ID}.controller`
|
|
72
|
+
);
|
|
73
|
+
function normalizeId(value) {
|
|
74
|
+
const normalized = value.trim();
|
|
75
|
+
return normalized || void 0;
|
|
76
|
+
}
|
|
77
|
+
function uniqueIds(ids) {
|
|
78
|
+
return Object.freeze(
|
|
79
|
+
Array.from(
|
|
80
|
+
new Set(ids.map((id) => normalizeId(id)).filter(Boolean))
|
|
81
|
+
)
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
function snapshotIds(data) {
|
|
85
|
+
const snapshot = data?.getSnapshot();
|
|
86
|
+
if (!snapshot) return [];
|
|
87
|
+
if (snapshot.mode === "console") {
|
|
88
|
+
return snapshot.visible.flatMap(
|
|
89
|
+
(message) => message.id ? [message.id] : []
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
return snapshot.visible.flatMap(({ entry }) => entry.id ? [entry.id] : []);
|
|
93
|
+
}
|
|
94
|
+
function createConsoleSelectionController(getData = () => void 0) {
|
|
95
|
+
let state = Object.freeze({
|
|
96
|
+
selectedIds: Object.freeze([])
|
|
97
|
+
});
|
|
98
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
99
|
+
const update = (selectedIds, anchorId) => {
|
|
100
|
+
state = Object.freeze({
|
|
101
|
+
selectedIds: uniqueIds(selectedIds),
|
|
102
|
+
...anchorId ? { anchorId } : {}
|
|
103
|
+
});
|
|
104
|
+
for (const listener of listeners) listener();
|
|
105
|
+
};
|
|
106
|
+
const controller = {
|
|
107
|
+
getState: () => state,
|
|
108
|
+
subscribe(listener) {
|
|
109
|
+
listeners.add(listener);
|
|
110
|
+
return () => listeners.delete(listener);
|
|
111
|
+
},
|
|
112
|
+
isSelected(id) {
|
|
113
|
+
const normalized = normalizeId(id);
|
|
114
|
+
return Boolean(normalized && state.selectedIds.includes(normalized));
|
|
115
|
+
},
|
|
116
|
+
select(id, additive = false) {
|
|
117
|
+
const normalized = normalizeId(id);
|
|
118
|
+
if (!normalized) return false;
|
|
119
|
+
const next = additive ? uniqueIds([...state.selectedIds, normalized]) : [normalized];
|
|
120
|
+
const changed = next.length !== state.selectedIds.length || next.some((value, index) => value !== state.selectedIds[index]);
|
|
121
|
+
if (changed || state.anchorId !== normalized) {
|
|
122
|
+
update(next, normalized);
|
|
123
|
+
}
|
|
124
|
+
return changed;
|
|
125
|
+
},
|
|
126
|
+
deselect(id) {
|
|
127
|
+
const normalized = normalizeId(id);
|
|
128
|
+
if (!normalized || !state.selectedIds.includes(normalized)) return false;
|
|
129
|
+
const next = state.selectedIds.filter((value) => value !== normalized);
|
|
130
|
+
update(next, state.anchorId === normalized ? void 0 : state.anchorId);
|
|
131
|
+
return true;
|
|
132
|
+
},
|
|
133
|
+
toggle(id) {
|
|
134
|
+
const normalized = normalizeId(id);
|
|
135
|
+
if (!normalized) return false;
|
|
136
|
+
if (controller.isSelected(normalized)) {
|
|
137
|
+
controller.deselect(normalized);
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
controller.select(normalized, true);
|
|
141
|
+
return true;
|
|
142
|
+
},
|
|
143
|
+
clear() {
|
|
144
|
+
if (state.selectedIds.length === 0 && !state.anchorId) return;
|
|
145
|
+
update([]);
|
|
146
|
+
},
|
|
147
|
+
setSelectedIds(ids) {
|
|
148
|
+
const next = uniqueIds(ids);
|
|
149
|
+
update(next, next.at(-1));
|
|
150
|
+
},
|
|
151
|
+
selectRange(fromId, toId) {
|
|
152
|
+
const ordered = snapshotIds(getData());
|
|
153
|
+
const start = ordered.indexOf(fromId);
|
|
154
|
+
const end = ordered.indexOf(toId);
|
|
155
|
+
if (start < 0 || end < 0) return state.selectedIds;
|
|
156
|
+
const [from, to] = start <= end ? [start, end] : [end, start];
|
|
157
|
+
const range = ordered.slice(from, to + 1);
|
|
158
|
+
update(range, toId);
|
|
159
|
+
return range;
|
|
160
|
+
},
|
|
161
|
+
getVisibleSelectedIds() {
|
|
162
|
+
const visible = new Set(snapshotIds(getData()));
|
|
163
|
+
return Object.freeze(state.selectedIds.filter((id) => visible.has(id)));
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
return controller;
|
|
167
|
+
}
|
|
168
|
+
function createDecoration(controller, locale, translations) {
|
|
169
|
+
return {
|
|
170
|
+
id: `${CONSOLE_SELECTION_ADDON_ID}:selected`,
|
|
171
|
+
placement: "gutter",
|
|
172
|
+
match({ message }) {
|
|
173
|
+
return Boolean(message.id && controller.isSelected(message.id));
|
|
174
|
+
},
|
|
175
|
+
render({ message }) {
|
|
176
|
+
if (!message.id || !controller.isSelected(message.id)) return void 0;
|
|
177
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SelectedMessageIndicator, { locale, translations });
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function createMessageAction(controller, locale, translations) {
|
|
182
|
+
return {
|
|
183
|
+
id: `${CONSOLE_SELECTION_ADDON_ID}:toggle`,
|
|
184
|
+
label: resolveAddonMessages(locale, translations).toggleSelection,
|
|
185
|
+
ariaLabel: resolveAddonMessages(locale, translations).toggleMessageSelection,
|
|
186
|
+
visible({ message }) {
|
|
187
|
+
return Boolean(message.id);
|
|
188
|
+
},
|
|
189
|
+
onSelect({ message }) {
|
|
190
|
+
if (message.id) controller.toggle(message.id);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function createConsoleSelectionAddon(options = {}) {
|
|
195
|
+
let activeData;
|
|
196
|
+
const controller = options.controller ?? createConsoleSelectionController(() => activeData);
|
|
197
|
+
const withDecoration = options.decoration !== false;
|
|
198
|
+
const withMessageAction = options.messageAction !== false;
|
|
199
|
+
return {
|
|
200
|
+
id: CONSOLE_SELECTION_ADDON_ID,
|
|
201
|
+
controller,
|
|
202
|
+
activate(host) {
|
|
203
|
+
activeData = host.services.get(consoleCore.consoleServices.data);
|
|
204
|
+
host.services.provide(consoleSelectionService, controller);
|
|
205
|
+
let decorationRegistration;
|
|
206
|
+
let actionRegistration;
|
|
207
|
+
const registerContributions = () => {
|
|
208
|
+
decorationRegistration?.dispose();
|
|
209
|
+
actionRegistration?.dispose();
|
|
210
|
+
if (withDecoration) {
|
|
211
|
+
decorationRegistration = host.extensions.register(
|
|
212
|
+
consoleCore.consoleExtensionPoints.messageDecoration,
|
|
213
|
+
createDecoration(controller, options.locale, options.translations),
|
|
214
|
+
{ id: `${CONSOLE_SELECTION_ADDON_ID}:selected` }
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
if (withMessageAction) {
|
|
218
|
+
actionRegistration = host.extensions.register(
|
|
219
|
+
consoleCore.consoleExtensionPoints.messageAction,
|
|
220
|
+
createMessageAction(
|
|
221
|
+
controller,
|
|
222
|
+
options.locale,
|
|
223
|
+
options.translations
|
|
224
|
+
),
|
|
225
|
+
{ id: `${CONSOLE_SELECTION_ADDON_ID}:toggle` }
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
registerContributions();
|
|
230
|
+
host.scope.defer(controller.subscribe(registerContributions));
|
|
231
|
+
host.scope.defer(() => decorationRegistration?.dispose());
|
|
232
|
+
host.scope.defer(() => actionRegistration?.dispose());
|
|
233
|
+
return () => {
|
|
234
|
+
activeData = void 0;
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
exports.CONSOLE_SELECTION_ADDON_ID = CONSOLE_SELECTION_ADDON_ID;
|
|
240
|
+
exports.SelectedMessageIndicator = SelectedMessageIndicator;
|
|
241
|
+
exports.consoleSelectionService = consoleSelectionService;
|
|
242
|
+
exports.createConsoleSelectionAddon = createConsoleSelectionAddon;
|
|
243
|
+
exports.createConsoleSelectionController = createConsoleSelectionController;
|
|
244
|
+
exports.resolveConsoleSelectionMessages = resolveAddonMessages;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type AddonTranslations } from "./localization.cjs";
|
|
2
|
+
export { resolveAddonMessages as resolveConsoleSelectionMessages } from "./localization.cjs";
|
|
3
|
+
export type { AddonTranslations as ConsoleSelectionTranslations } from "./localization.cjs";
|
|
4
|
+
export { SelectedMessageIndicator } from "./components/SelectedMessageIndicator/SelectedMessageIndicator.cjs";
|
|
5
|
+
import { type ConsoleAddon, type ConsoleDataService } from "@moyarich/console-core";
|
|
6
|
+
export declare const CONSOLE_SELECTION_ADDON_ID = "@moyarich/console-addon-selection";
|
|
7
|
+
export interface ConsoleSelectionState {
|
|
8
|
+
readonly selectedIds: readonly string[];
|
|
9
|
+
readonly anchorId?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ConsoleSelectionController {
|
|
12
|
+
getState(): ConsoleSelectionState;
|
|
13
|
+
subscribe(listener: () => void): () => void;
|
|
14
|
+
isSelected(id: string): boolean;
|
|
15
|
+
select(id: string, additive?: boolean): boolean;
|
|
16
|
+
deselect(id: string): boolean;
|
|
17
|
+
toggle(id: string): boolean;
|
|
18
|
+
clear(): void;
|
|
19
|
+
setSelectedIds(ids: readonly string[]): void;
|
|
20
|
+
selectRange(fromId: string, toId: string): readonly string[];
|
|
21
|
+
getVisibleSelectedIds(): readonly string[];
|
|
22
|
+
}
|
|
23
|
+
export interface ConsoleSelectionAddonOptions {
|
|
24
|
+
locale?: string;
|
|
25
|
+
translations?: AddonTranslations;
|
|
26
|
+
controller?: ConsoleSelectionController;
|
|
27
|
+
decoration?: boolean;
|
|
28
|
+
messageAction?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface ConsoleSelectionAddon extends ConsoleAddon {
|
|
31
|
+
readonly controller: ConsoleSelectionController;
|
|
32
|
+
}
|
|
33
|
+
export declare const consoleSelectionService: import("@moyarich/console-core").ConsoleServiceToken<ConsoleSelectionController>;
|
|
34
|
+
export declare function createConsoleSelectionController(getData?: () => ConsoleDataService | undefined): ConsoleSelectionController;
|
|
35
|
+
export declare function createConsoleSelectionAddon(options?: ConsoleSelectionAddonOptions): ConsoleSelectionAddon;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type AddonTranslations } from "./localization.js";
|
|
2
|
+
export { resolveAddonMessages as resolveConsoleSelectionMessages } from "./localization.js";
|
|
3
|
+
export type { AddonTranslations as ConsoleSelectionTranslations } from "./localization.js";
|
|
4
|
+
export { SelectedMessageIndicator } from "./components/SelectedMessageIndicator/SelectedMessageIndicator.js";
|
|
5
|
+
import { type ConsoleAddon, type ConsoleDataService } from "@moyarich/console-core";
|
|
6
|
+
export declare const CONSOLE_SELECTION_ADDON_ID = "@moyarich/console-addon-selection";
|
|
7
|
+
export interface ConsoleSelectionState {
|
|
8
|
+
readonly selectedIds: readonly string[];
|
|
9
|
+
readonly anchorId?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface ConsoleSelectionController {
|
|
12
|
+
getState(): ConsoleSelectionState;
|
|
13
|
+
subscribe(listener: () => void): () => void;
|
|
14
|
+
isSelected(id: string): boolean;
|
|
15
|
+
select(id: string, additive?: boolean): boolean;
|
|
16
|
+
deselect(id: string): boolean;
|
|
17
|
+
toggle(id: string): boolean;
|
|
18
|
+
clear(): void;
|
|
19
|
+
setSelectedIds(ids: readonly string[]): void;
|
|
20
|
+
selectRange(fromId: string, toId: string): readonly string[];
|
|
21
|
+
getVisibleSelectedIds(): readonly string[];
|
|
22
|
+
}
|
|
23
|
+
export interface ConsoleSelectionAddonOptions {
|
|
24
|
+
locale?: string;
|
|
25
|
+
translations?: AddonTranslations;
|
|
26
|
+
controller?: ConsoleSelectionController;
|
|
27
|
+
decoration?: boolean;
|
|
28
|
+
messageAction?: boolean;
|
|
29
|
+
}
|
|
30
|
+
export interface ConsoleSelectionAddon extends ConsoleAddon {
|
|
31
|
+
readonly controller: ConsoleSelectionController;
|
|
32
|
+
}
|
|
33
|
+
export declare const consoleSelectionService: import("@moyarich/console-core").ConsoleServiceToken<ConsoleSelectionController>;
|
|
34
|
+
export declare function createConsoleSelectionController(getData?: () => ConsoleDataService | undefined): ConsoleSelectionController;
|
|
35
|
+
export declare function createConsoleSelectionAddon(options?: ConsoleSelectionAddonOptions): ConsoleSelectionAddon;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createConsoleServiceToken, consoleServices, consoleExtensionPoints } from "@moyarich/console-core";
|
|
3
|
+
const selectedMessage$3 = "Selected message";
|
|
4
|
+
const selected$3 = "Selected";
|
|
5
|
+
const toggleSelection$3 = "Toggle selection";
|
|
6
|
+
const toggleMessageSelection$3 = "Toggle message selection";
|
|
7
|
+
const en = {
|
|
8
|
+
selectedMessage: selectedMessage$3,
|
|
9
|
+
selected: selected$3,
|
|
10
|
+
toggleSelection: toggleSelection$3,
|
|
11
|
+
toggleMessageSelection: toggleMessageSelection$3
|
|
12
|
+
};
|
|
13
|
+
const selectedMessage$2 = "Mensaje seleccionado";
|
|
14
|
+
const selected$2 = "Seleccionado";
|
|
15
|
+
const toggleSelection$2 = "Alternar selección";
|
|
16
|
+
const toggleMessageSelection$2 = "Alternar selección del mensaje";
|
|
17
|
+
const es = {
|
|
18
|
+
selectedMessage: selectedMessage$2,
|
|
19
|
+
selected: selected$2,
|
|
20
|
+
toggleSelection: toggleSelection$2,
|
|
21
|
+
toggleMessageSelection: toggleMessageSelection$2
|
|
22
|
+
};
|
|
23
|
+
const selectedMessage$1 = "Message sélectionné";
|
|
24
|
+
const selected$1 = "Sélectionné";
|
|
25
|
+
const toggleSelection$1 = "Activer/désactiver la sélection";
|
|
26
|
+
const toggleMessageSelection$1 = "Activer/désactiver la sélection du message";
|
|
27
|
+
const fr = {
|
|
28
|
+
selectedMessage: selectedMessage$1,
|
|
29
|
+
selected: selected$1,
|
|
30
|
+
toggleSelection: toggleSelection$1,
|
|
31
|
+
toggleMessageSelection: toggleMessageSelection$1
|
|
32
|
+
};
|
|
33
|
+
const selectedMessage = "Mensagem selecionada";
|
|
34
|
+
const selected = "Selecionado";
|
|
35
|
+
const toggleSelection = "Alternar seleção";
|
|
36
|
+
const toggleMessageSelection = "Alternar seleção da mensagem";
|
|
37
|
+
const pt = {
|
|
38
|
+
selectedMessage,
|
|
39
|
+
selected,
|
|
40
|
+
toggleSelection,
|
|
41
|
+
toggleMessageSelection
|
|
42
|
+
};
|
|
43
|
+
const dictionaries = { en, es, fr, pt };
|
|
44
|
+
function resolveAddonMessages(locale = "en", overrides) {
|
|
45
|
+
const tag = locale.replace(/_/g, "-").toLowerCase();
|
|
46
|
+
return {
|
|
47
|
+
...en,
|
|
48
|
+
...dictionaries[tag] ?? dictionaries[tag.split("-")[0]] ?? {},
|
|
49
|
+
...overrides
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
function SelectedMessageIndicator({
|
|
53
|
+
locale = "en",
|
|
54
|
+
translations
|
|
55
|
+
} = {}) {
|
|
56
|
+
const t = resolveAddonMessages(locale, translations);
|
|
57
|
+
return /* @__PURE__ */ jsx(
|
|
58
|
+
"span",
|
|
59
|
+
{
|
|
60
|
+
"aria-label": t.selectedMessage,
|
|
61
|
+
title: t.selected,
|
|
62
|
+
style: { fontSize: 12, lineHeight: 1 },
|
|
63
|
+
children: "●"
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
const CONSOLE_SELECTION_ADDON_ID = "@moyarich/console-addon-selection";
|
|
68
|
+
const consoleSelectionService = createConsoleServiceToken(
|
|
69
|
+
`${CONSOLE_SELECTION_ADDON_ID}.controller`
|
|
70
|
+
);
|
|
71
|
+
function normalizeId(value) {
|
|
72
|
+
const normalized = value.trim();
|
|
73
|
+
return normalized || void 0;
|
|
74
|
+
}
|
|
75
|
+
function uniqueIds(ids) {
|
|
76
|
+
return Object.freeze(
|
|
77
|
+
Array.from(
|
|
78
|
+
new Set(ids.map((id) => normalizeId(id)).filter(Boolean))
|
|
79
|
+
)
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
function snapshotIds(data) {
|
|
83
|
+
const snapshot = data?.getSnapshot();
|
|
84
|
+
if (!snapshot) return [];
|
|
85
|
+
if (snapshot.mode === "console") {
|
|
86
|
+
return snapshot.visible.flatMap(
|
|
87
|
+
(message) => message.id ? [message.id] : []
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
return snapshot.visible.flatMap(({ entry }) => entry.id ? [entry.id] : []);
|
|
91
|
+
}
|
|
92
|
+
function createConsoleSelectionController(getData = () => void 0) {
|
|
93
|
+
let state = Object.freeze({
|
|
94
|
+
selectedIds: Object.freeze([])
|
|
95
|
+
});
|
|
96
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
97
|
+
const update = (selectedIds, anchorId) => {
|
|
98
|
+
state = Object.freeze({
|
|
99
|
+
selectedIds: uniqueIds(selectedIds),
|
|
100
|
+
...anchorId ? { anchorId } : {}
|
|
101
|
+
});
|
|
102
|
+
for (const listener of listeners) listener();
|
|
103
|
+
};
|
|
104
|
+
const controller = {
|
|
105
|
+
getState: () => state,
|
|
106
|
+
subscribe(listener) {
|
|
107
|
+
listeners.add(listener);
|
|
108
|
+
return () => listeners.delete(listener);
|
|
109
|
+
},
|
|
110
|
+
isSelected(id) {
|
|
111
|
+
const normalized = normalizeId(id);
|
|
112
|
+
return Boolean(normalized && state.selectedIds.includes(normalized));
|
|
113
|
+
},
|
|
114
|
+
select(id, additive = false) {
|
|
115
|
+
const normalized = normalizeId(id);
|
|
116
|
+
if (!normalized) return false;
|
|
117
|
+
const next = additive ? uniqueIds([...state.selectedIds, normalized]) : [normalized];
|
|
118
|
+
const changed = next.length !== state.selectedIds.length || next.some((value, index) => value !== state.selectedIds[index]);
|
|
119
|
+
if (changed || state.anchorId !== normalized) {
|
|
120
|
+
update(next, normalized);
|
|
121
|
+
}
|
|
122
|
+
return changed;
|
|
123
|
+
},
|
|
124
|
+
deselect(id) {
|
|
125
|
+
const normalized = normalizeId(id);
|
|
126
|
+
if (!normalized || !state.selectedIds.includes(normalized)) return false;
|
|
127
|
+
const next = state.selectedIds.filter((value) => value !== normalized);
|
|
128
|
+
update(next, state.anchorId === normalized ? void 0 : state.anchorId);
|
|
129
|
+
return true;
|
|
130
|
+
},
|
|
131
|
+
toggle(id) {
|
|
132
|
+
const normalized = normalizeId(id);
|
|
133
|
+
if (!normalized) return false;
|
|
134
|
+
if (controller.isSelected(normalized)) {
|
|
135
|
+
controller.deselect(normalized);
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
controller.select(normalized, true);
|
|
139
|
+
return true;
|
|
140
|
+
},
|
|
141
|
+
clear() {
|
|
142
|
+
if (state.selectedIds.length === 0 && !state.anchorId) return;
|
|
143
|
+
update([]);
|
|
144
|
+
},
|
|
145
|
+
setSelectedIds(ids) {
|
|
146
|
+
const next = uniqueIds(ids);
|
|
147
|
+
update(next, next.at(-1));
|
|
148
|
+
},
|
|
149
|
+
selectRange(fromId, toId) {
|
|
150
|
+
const ordered = snapshotIds(getData());
|
|
151
|
+
const start = ordered.indexOf(fromId);
|
|
152
|
+
const end = ordered.indexOf(toId);
|
|
153
|
+
if (start < 0 || end < 0) return state.selectedIds;
|
|
154
|
+
const [from, to] = start <= end ? [start, end] : [end, start];
|
|
155
|
+
const range = ordered.slice(from, to + 1);
|
|
156
|
+
update(range, toId);
|
|
157
|
+
return range;
|
|
158
|
+
},
|
|
159
|
+
getVisibleSelectedIds() {
|
|
160
|
+
const visible = new Set(snapshotIds(getData()));
|
|
161
|
+
return Object.freeze(state.selectedIds.filter((id) => visible.has(id)));
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
return controller;
|
|
165
|
+
}
|
|
166
|
+
function createDecoration(controller, locale, translations) {
|
|
167
|
+
return {
|
|
168
|
+
id: `${CONSOLE_SELECTION_ADDON_ID}:selected`,
|
|
169
|
+
placement: "gutter",
|
|
170
|
+
match({ message }) {
|
|
171
|
+
return Boolean(message.id && controller.isSelected(message.id));
|
|
172
|
+
},
|
|
173
|
+
render({ message }) {
|
|
174
|
+
if (!message.id || !controller.isSelected(message.id)) return void 0;
|
|
175
|
+
return /* @__PURE__ */ jsx(SelectedMessageIndicator, { locale, translations });
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function createMessageAction(controller, locale, translations) {
|
|
180
|
+
return {
|
|
181
|
+
id: `${CONSOLE_SELECTION_ADDON_ID}:toggle`,
|
|
182
|
+
label: resolveAddonMessages(locale, translations).toggleSelection,
|
|
183
|
+
ariaLabel: resolveAddonMessages(locale, translations).toggleMessageSelection,
|
|
184
|
+
visible({ message }) {
|
|
185
|
+
return Boolean(message.id);
|
|
186
|
+
},
|
|
187
|
+
onSelect({ message }) {
|
|
188
|
+
if (message.id) controller.toggle(message.id);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function createConsoleSelectionAddon(options = {}) {
|
|
193
|
+
let activeData;
|
|
194
|
+
const controller = options.controller ?? createConsoleSelectionController(() => activeData);
|
|
195
|
+
const withDecoration = options.decoration !== false;
|
|
196
|
+
const withMessageAction = options.messageAction !== false;
|
|
197
|
+
return {
|
|
198
|
+
id: CONSOLE_SELECTION_ADDON_ID,
|
|
199
|
+
controller,
|
|
200
|
+
activate(host) {
|
|
201
|
+
activeData = host.services.get(consoleServices.data);
|
|
202
|
+
host.services.provide(consoleSelectionService, controller);
|
|
203
|
+
let decorationRegistration;
|
|
204
|
+
let actionRegistration;
|
|
205
|
+
const registerContributions = () => {
|
|
206
|
+
decorationRegistration?.dispose();
|
|
207
|
+
actionRegistration?.dispose();
|
|
208
|
+
if (withDecoration) {
|
|
209
|
+
decorationRegistration = host.extensions.register(
|
|
210
|
+
consoleExtensionPoints.messageDecoration,
|
|
211
|
+
createDecoration(controller, options.locale, options.translations),
|
|
212
|
+
{ id: `${CONSOLE_SELECTION_ADDON_ID}:selected` }
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
if (withMessageAction) {
|
|
216
|
+
actionRegistration = host.extensions.register(
|
|
217
|
+
consoleExtensionPoints.messageAction,
|
|
218
|
+
createMessageAction(
|
|
219
|
+
controller,
|
|
220
|
+
options.locale,
|
|
221
|
+
options.translations
|
|
222
|
+
),
|
|
223
|
+
{ id: `${CONSOLE_SELECTION_ADDON_ID}:toggle` }
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
registerContributions();
|
|
228
|
+
host.scope.defer(controller.subscribe(registerContributions));
|
|
229
|
+
host.scope.defer(() => decorationRegistration?.dispose());
|
|
230
|
+
host.scope.defer(() => actionRegistration?.dispose());
|
|
231
|
+
return () => {
|
|
232
|
+
activeData = void 0;
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
export {
|
|
238
|
+
CONSOLE_SELECTION_ADDON_ID,
|
|
239
|
+
SelectedMessageIndicator,
|
|
240
|
+
consoleSelectionService,
|
|
241
|
+
createConsoleSelectionAddon,
|
|
242
|
+
createConsoleSelectionController,
|
|
243
|
+
resolveAddonMessages as resolveConsoleSelectionMessages
|
|
244
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,64 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@moyarich/console-addon-selection",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "First-party semantic output selection for @moyarich/console hosts.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"default": "./dist/index.cjs"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"registry": "https://npm.pkg.github.com"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "vite build && tsc -p tsconfig.build.json && node ../../../scripts/prepare-cjs-types.mjs",
|
|
30
|
+
"typecheck": "tsc --noEmit"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"@moyarich/console-core": "^0.2.0",
|
|
34
|
+
"react": ">=18"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@moyarich/console-core": "0.2.0",
|
|
38
|
+
"@types/react": "^19.1.12",
|
|
39
|
+
"react": "^19.2.7",
|
|
40
|
+
"typescript": "^5.9.2",
|
|
41
|
+
"vite": "^7.1.5"
|
|
42
|
+
},
|
|
43
|
+
"repository": {
|
|
44
|
+
"type": "git",
|
|
45
|
+
"url": "git+https://github.com/moyarich/console.git",
|
|
46
|
+
"directory": "packages/addons/selection"
|
|
47
|
+
},
|
|
48
|
+
"bugs": {
|
|
49
|
+
"url": "https://github.com/moyarich/console/issues"
|
|
50
|
+
},
|
|
51
|
+
"homepage": "https://github.com/moyarich/console#readme",
|
|
52
|
+
"keywords": [
|
|
53
|
+
"console",
|
|
54
|
+
"addon",
|
|
55
|
+
"selection",
|
|
56
|
+
"developer-tools"
|
|
57
|
+
],
|
|
58
|
+
"publisher": "moyarich",
|
|
59
|
+
"author": "Moya Richards",
|
|
60
|
+
"engines": {
|
|
61
|
+
"node": ">=24"
|
|
62
|
+
},
|
|
63
|
+
"private": false
|
|
64
|
+
}
|