@tensor_1/react 2.46.0 → 2.48.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 +509 -1
- package/dist/{SchedulingCalendar-B6TakO2h.d.ts → SchedulingCalendar-WWyFL3Eo.d.ts} +51 -2
- package/dist/announce.d.ts +10 -0
- package/dist/announce.js +30 -0
- package/dist/chart-analytic.cjs +33 -25
- package/dist/chart-preset.cjs +23 -15
- package/dist/chart.cjs +23 -15
- package/dist/combobox-model.d.ts +10 -1
- package/dist/combobox-model.js +15 -0
- package/dist/command-palette-model.d.ts +44 -0
- package/dist/command-palette-model.js +36 -0
- package/dist/components/AccountMenu.d.ts +44 -0
- package/dist/components/AccountMenu.js +43 -0
- package/dist/components/AppShell.d.ts +45 -2
- package/dist/components/AppShell.js +116 -5
- package/dist/components/AuditLog.d.ts +128 -0
- package/dist/components/AuditLog.js +196 -0
- package/dist/components/BrandProfiles.js +4 -3
- package/dist/components/Breadcrumbs.d.ts +9 -2
- package/dist/components/Breadcrumbs.js +3 -2
- package/dist/components/BusyBar.d.ts +13 -0
- package/dist/components/BusyBar.js +10 -0
- package/dist/components/BusyRegion.d.ts +18 -0
- package/dist/components/BusyRegion.js +12 -0
- package/dist/components/Button.d.ts +33 -5
- package/dist/components/Button.js +12 -6
- package/dist/components/ButtonFeedback.d.ts +30 -0
- package/dist/components/ButtonFeedback.js +78 -0
- package/dist/components/Card.d.ts +18 -1
- package/dist/components/Card.js +5 -1
- package/dist/components/ChangeHighlight.d.ts +30 -0
- package/dist/components/ChangeHighlight.js +21 -0
- package/dist/components/ChartCore.js +2 -1
- package/dist/components/Checkbox.d.ts +27 -1
- package/dist/components/Checkbox.js +31 -2
- package/dist/components/CodeDisplay.d.ts +65 -0
- package/dist/components/CodeDisplay.js +124 -0
- package/dist/components/Combobox.d.ts +27 -6
- package/dist/components/Combobox.js +195 -58
- package/dist/components/CommandPalette.d.ts +36 -1
- package/dist/components/CommandPalette.js +254 -2
- package/dist/components/ContactCard.d.ts +66 -0
- package/dist/components/ContactCard.js +74 -0
- package/dist/components/Count.d.ts +24 -0
- package/dist/components/Count.js +32 -0
- package/dist/components/DataWorkspace.d.ts +167 -0
- package/dist/components/DataWorkspace.js +383 -0
- package/dist/components/DateFieldParts.d.ts +2 -1
- package/dist/components/DateFieldParts.js +7 -0
- package/dist/components/DatePicker.d.ts +9 -2
- package/dist/components/DatePicker.js +67 -28
- package/dist/components/DateRangePicker.d.ts +12 -2
- package/dist/components/DateRangePicker.js +13 -12
- package/dist/components/DelayedRender.d.ts +15 -0
- package/dist/components/DelayedRender.js +10 -0
- package/dist/components/DetailPage.d.ts +7 -1
- package/dist/components/DetailPage.js +2 -1
- package/dist/components/Dialogs.d.ts +71 -10
- package/dist/components/Dialogs.js +130 -30
- package/dist/components/DiffViewer.d.ts +23 -3
- package/dist/components/DiffViewer.js +26 -12
- package/dist/components/DiscardPrompt.d.ts +1 -0
- package/dist/components/DiscardPrompt.js +16 -0
- package/dist/components/DisplayPreferences.d.ts +83 -0
- package/dist/components/DisplayPreferences.js +185 -0
- package/dist/components/Drawer.d.ts +1 -0
- package/dist/components/EditorialHome.d.ts +23 -3
- package/dist/components/EditorialHome.js +16 -11
- package/dist/components/EntityPicker.d.ts +20 -3
- package/dist/components/EntityPicker.js +32 -13
- package/dist/components/FilterEditor.d.ts +18 -4
- package/dist/components/FilterEditor.js +141 -19
- package/dist/components/InfoTip.js +11 -12
- package/dist/components/InlineEdit.d.ts +87 -20
- package/dist/components/InlineEdit.js +197 -54
- package/dist/components/Input.d.ts +12 -2
- package/dist/components/Input.js +5 -3
- package/dist/components/Kbd.d.ts +6 -1
- package/dist/components/Kbd.js +6 -6
- package/dist/components/Lightbox.d.ts +41 -5
- package/dist/components/Lightbox.js +95 -9
- package/dist/components/MatchReview.d.ts +40 -1
- package/dist/components/MatchReview.js +130 -4
- package/dist/components/MetricInput.js +3 -2
- package/dist/components/Modal.d.ts +3 -1
- package/dist/components/Modal.js +13 -4
- package/dist/components/NavFavourites.d.ts +5 -0
- package/dist/components/NavFavourites.js +7 -7
- package/dist/components/OtpInput.d.ts +33 -0
- package/dist/components/OtpInput.js +123 -0
- package/dist/components/PageHeader.d.ts +7 -1
- package/dist/components/PageHeader.js +2 -2
- package/dist/components/Pagination.js +6 -5
- package/dist/components/PasswordInput.d.ts +34 -0
- package/dist/components/PasswordInput.js +101 -0
- package/dist/components/Peek.js +3 -3
- package/dist/components/Popover.js +2 -0
- package/dist/components/PrintLayout.d.ts +63 -0
- package/dist/components/PrintLayout.js +114 -0
- package/dist/components/QrCode.d.ts +47 -0
- package/dist/components/QrCode.js +55 -0
- package/dist/components/QrScanner.d.ts +95 -0
- package/dist/components/QrScanner.js +266 -0
- package/dist/components/RelationshipGraph.d.ts +32 -1
- package/dist/components/RelationshipGraph.js +18 -5
- package/dist/components/RelationshipGraphLayered.d.ts +1 -1
- package/dist/components/RelationshipGraphLayered.js +190 -115
- package/dist/components/RelationshipGraphList.js +33 -6
- package/dist/components/RuleBuilder.js +39 -7
- package/dist/components/SaveStatus.d.ts +7 -1
- package/dist/components/SaveStatus.js +13 -4
- package/dist/components/SchedulingAgenda.d.ts +3 -1
- package/dist/components/SchedulingCalendar.d.ts +3 -1
- package/dist/components/SchedulingCalendar.js +43 -4
- package/dist/components/SchedulingResourceDay.d.ts +57 -0
- package/dist/components/SchedulingResourceDay.js +287 -0
- package/dist/components/SchedulingTimeGrid.d.ts +3 -1
- package/dist/components/SchedulingTimeline.d.ts +3 -1
- package/dist/components/SearchBar.d.ts +1 -0
- package/dist/components/SearchSuggest.d.ts +23 -3
- package/dist/components/SearchSuggest.js +48 -17
- package/dist/components/Segmented.d.ts +39 -4
- package/dist/components/Segmented.js +31 -3
- package/dist/components/Select.d.ts +3 -2
- package/dist/components/Select.js +1 -1
- package/dist/components/ShortcutHint.d.ts +11 -10
- package/dist/components/ShortcutHint.js +44 -38
- package/dist/components/Sidebar.d.ts +36 -4
- package/dist/components/Sidebar.js +37 -12
- package/dist/components/SortableList.d.ts +45 -0
- package/dist/components/SortableList.js +134 -0
- package/dist/components/Spinner.d.ts +7 -1
- package/dist/components/Spinner.js +7 -1
- package/dist/components/Stat.d.ts +28 -3
- package/dist/components/Stat.js +13 -3
- package/dist/components/States.d.ts +7 -1
- package/dist/components/States.js +7 -1
- package/dist/components/StatusPill.d.ts +14 -3
- package/dist/components/StatusPill.js +11 -3
- package/dist/components/Steps.js +2 -1
- package/dist/components/Table.d.ts +16 -2
- package/dist/components/Table.js +8 -4
- package/dist/components/TableControls.js +18 -58
- package/dist/components/TableOverflowProbe.d.ts +12 -0
- package/dist/components/TableOverflowProbe.js +27 -0
- package/dist/components/Tabs.d.ts +2 -1
- package/dist/components/Tabs.js +1 -0
- package/dist/components/TagInput.d.ts +67 -0
- package/dist/components/TagInput.js +342 -0
- package/dist/components/Textarea.d.ts +5 -0
- package/dist/components/Textarea.js +2 -2
- package/dist/components/TimePicker.d.ts +80 -0
- package/dist/components/TimePicker.js +347 -0
- package/dist/components/Toast.js +3 -2
- package/dist/components/Tooltip.d.ts +8 -4
- package/dist/components/Tooltip.js +24 -21
- package/dist/components/Tree.d.ts +8 -0
- package/dist/components/Tree.js +11 -5
- package/dist/display-preferences-model.d.ts +53 -0
- package/dist/display-preferences-model.js +64 -0
- package/dist/emoji.cjs +28 -35
- package/dist/filter-model.d.ts +59 -3
- package/dist/filter-model.js +67 -2
- package/dist/hooks/useChangeHighlight.d.ts +33 -0
- package/dist/hooks/useChangeHighlight.js +44 -0
- package/dist/hooks/useDelayedPending.d.ts +22 -0
- package/dist/hooks/useDelayedPending.js +35 -0
- package/dist/hooks/useDialog.d.ts +5 -0
- package/dist/hooks/useDialog.js +3 -2
- package/dist/hooks/useOptimisticValue.d.ts +51 -0
- package/dist/hooks/useOptimisticValue.js +61 -0
- package/dist/hooks/useReducedMotion.d.ts +4 -1
- package/dist/hooks/useReducedMotion.js +7 -1
- package/dist/hooks/useResolvedFilterLabels.d.ts +15 -0
- package/dist/hooks/useResolvedFilterLabels.js +34 -0
- package/dist/hooks/useVirtualRows.d.ts +21 -2
- package/dist/hooks/useVirtualRows.js +30 -3
- package/dist/icons/Icon.d.ts +1 -1
- package/dist/index.cjs +18977 -13378
- package/dist/index.d.cts +3065 -664
- package/dist/index.d.ts +46 -16
- package/dist/index.js +149 -7
- package/dist/labels-context.d.ts +93 -3
- package/dist/motion-timing.d.ts +8 -0
- package/dist/motion-timing.js +8 -0
- package/dist/overlay-stack.d.ts +6 -0
- package/dist/overlay-stack.js +13 -0
- package/dist/qr-model.d.ts +65 -0
- package/dist/qr-model.js +323 -0
- package/dist/relationship-graph-model.d.ts +78 -3
- package/dist/relationship-graph-model.js +112 -5
- package/dist/reorder.d.ts +30 -0
- package/dist/reorder.js +74 -0
- package/dist/rich-text.cjs +4 -2
- package/dist/scheduling-resource-model.d.ts +76 -0
- package/dist/scheduling-resource-model.js +74 -0
- package/dist/search-suggest-model.js +3 -1
- package/dist/shell-context.d.ts +11 -0
- package/dist/shell-context.js +7 -0
- package/dist/time-field-model.d.ts +46 -0
- package/dist/time-field-model.js +152 -0
- package/dist/toast-store.d.ts +17 -1
- package/dist/toast-store.js +23 -7
- package/package.json +2 -1
package/dist/labels-context.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
3
|
import { PaginationLabels } from './components/Pagination.js';
|
|
4
|
-
import { e as SchedulingCalendarLabels } from './SchedulingCalendar-
|
|
4
|
+
import { e as SchedulingCalendarLabels } from './SchedulingCalendar-WWyFL3Eo.js';
|
|
5
5
|
import { DateRangePickerLabels } from './components/DateRangePicker.js';
|
|
6
6
|
import { DatePickerLabels, DateTimePickerLabels } from './components/DatePicker.js';
|
|
7
7
|
import { SchedulingTimelineLabels } from './components/SchedulingTimeline.js';
|
|
@@ -17,9 +17,28 @@ import { OrgChartLabels } from './components/OrgChart.js';
|
|
|
17
17
|
import { InlineEditLabels } from './components/InlineEdit.js';
|
|
18
18
|
import { DiscardPromptLabels } from './components/DiscardPrompt.js';
|
|
19
19
|
import { SearchBarLabels } from './components/SearchBar.js';
|
|
20
|
+
import { LightboxLabels } from './components/Lightbox.js';
|
|
21
|
+
import { SortableListLabels } from './components/SortableList.js';
|
|
22
|
+
import { DiffViewerLabels } from './components/DiffViewer.js';
|
|
23
|
+
import { MatchReviewLabels } from './components/MatchReview.js';
|
|
24
|
+
import { QrCodeLabels } from './components/QrCode.js';
|
|
25
|
+
import { CodeDisplayLabels } from './components/CodeDisplay.js';
|
|
26
|
+
import { ContactCardLabels } from './components/ContactCard.js';
|
|
27
|
+
import { PrintLayoutLabels } from './components/PrintLayout.js';
|
|
28
|
+
import { QrScannerLabels } from './components/QrScanner.js';
|
|
29
|
+
import { PasswordInputLabels } from './components/PasswordInput.js';
|
|
30
|
+
import { TimePickerLabels } from './components/TimePicker.js';
|
|
31
|
+
import { TagInputLabels } from './components/TagInput.js';
|
|
32
|
+
import { AccountMenuLabels } from './components/AccountMenu.js';
|
|
33
|
+
import { DisplayPreferencesLabels } from './components/DisplayPreferences.js';
|
|
34
|
+
import { ButtonResultLabels } from './components/ButtonFeedback.js';
|
|
35
|
+
import { AuditLogLabels } from './components/AuditLog.js';
|
|
36
|
+
import { DataWorkspaceLabels } from './components/DataWorkspace.js';
|
|
20
37
|
import './link.js';
|
|
21
38
|
import './calendar-model.js';
|
|
22
39
|
import './scheduling-calendar-model.js';
|
|
40
|
+
import './components/SchedulingResourceDay.js';
|
|
41
|
+
import './scheduling-resource-model.js';
|
|
23
42
|
import './overlay-position.js';
|
|
24
43
|
import './scheduling-timeline-model.js';
|
|
25
44
|
import './text-diff-model.js';
|
|
@@ -31,6 +50,14 @@ import './file-model.js';
|
|
|
31
50
|
import './components/SearchSuggest.js';
|
|
32
51
|
import './components/Button.js';
|
|
33
52
|
import './components/Kbd.js';
|
|
53
|
+
import './diff-model.js';
|
|
54
|
+
import './qr-model.js';
|
|
55
|
+
import './components/Input.js';
|
|
56
|
+
import './components/Avatar.js';
|
|
57
|
+
import './display-preferences-model.js';
|
|
58
|
+
import './components/StatusPill.js';
|
|
59
|
+
import './components/Table.js';
|
|
60
|
+
import './components/TableControls.js';
|
|
34
61
|
|
|
35
62
|
/**
|
|
36
63
|
* Kit chrome strings by component (HAR-1358; TENSOR C20, MOTUS executive summary #3).
|
|
@@ -42,6 +69,8 @@ import './components/Kbd.js';
|
|
|
42
69
|
* on the server.
|
|
43
70
|
*/
|
|
44
71
|
interface UixLabels {
|
|
72
|
+
/** The words a `Button` with `result` shows for a moment after its action (HAR-2581). */
|
|
73
|
+
buttonResult?: Partial<ButtonResultLabels>;
|
|
45
74
|
modal?: {
|
|
46
75
|
close?: string;
|
|
47
76
|
};
|
|
@@ -55,16 +84,28 @@ interface UixLabels {
|
|
|
55
84
|
next?: string;
|
|
56
85
|
close?: string;
|
|
57
86
|
};
|
|
87
|
+
/** `Lightbox` (HAR-1826): previous / next / close, the counter, the zoom toggle. */
|
|
88
|
+
lightbox?: Partial<LightboxLabels>;
|
|
58
89
|
toast?: {
|
|
59
90
|
dismiss?: string;
|
|
60
91
|
};
|
|
61
92
|
toaster?: {
|
|
62
93
|
region?: string;
|
|
63
94
|
};
|
|
95
|
+
/**
|
|
96
|
+
* `openNav`: the phone-tier button that opens the navigation drawer; `navigation`: that
|
|
97
|
+
* drawer's title (HAR-1371).
|
|
98
|
+
*/
|
|
64
99
|
appShell?: {
|
|
65
100
|
skipToContent?: string;
|
|
66
101
|
exitFocus?: string;
|
|
102
|
+
openNav?: string;
|
|
103
|
+
navigation?: string;
|
|
67
104
|
};
|
|
105
|
+
/** `ThemeSwitcher` and `DisplayPreferences` (HAR-1372): the setting names and their choices. */
|
|
106
|
+
displayPreferences?: Partial<DisplayPreferencesLabels>;
|
|
107
|
+
/** `AccountMenu` (HAR-1371): the menu's name. */
|
|
108
|
+
accountMenu?: Partial<AccountMenuLabels>;
|
|
68
109
|
sidebar?: {
|
|
69
110
|
expand?: string;
|
|
70
111
|
collapse?: string;
|
|
@@ -74,32 +115,65 @@ interface UixLabels {
|
|
|
74
115
|
};
|
|
75
116
|
/** `SearchBar` (HAR-2030): the clear button's name and the submit button's text. */
|
|
76
117
|
searchBar?: Partial<SearchBarLabels>;
|
|
77
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* `resultsOne` / `resultsMany`: the polite result count; `{count}`. Items mode (HAR-1378):
|
|
120
|
+
* `empty` when nothing matches, `recent` the heading of the recent items.
|
|
121
|
+
*/
|
|
78
122
|
commandPalette?: {
|
|
79
123
|
input?: string;
|
|
80
124
|
resultsOne?: string;
|
|
81
125
|
resultsMany?: string;
|
|
126
|
+
empty?: string;
|
|
127
|
+
recent?: string;
|
|
82
128
|
};
|
|
129
|
+
/** `QrCode` (HAR-1251): the text shown when the value is too long for a QR code. */
|
|
130
|
+
qrCode?: Partial<QrCodeLabels>;
|
|
131
|
+
/** `CodeDisplay` (HAR-1253): the countdown, the expiry announcements, the copy button's words. */
|
|
132
|
+
codeDisplay?: Partial<CodeDisplayLabels>;
|
|
133
|
+
/** `ContactCard` (HAR-1379): the Email / Call actions and the erased and unavailable states. */
|
|
134
|
+
contactCard?: Partial<ContactCardLabels>;
|
|
135
|
+
/** `PrintSignature` (HAR-986): the captions of the signature line and the stamp box. */
|
|
136
|
+
printLayout?: Partial<PrintLayoutLabels>;
|
|
137
|
+
/** `QrScanner` (HAR-1254): the start / stop buttons, every state's title and text, the read announcement. */
|
|
138
|
+
qrScanner?: Partial<QrScannerLabels>;
|
|
83
139
|
entityPicker?: Partial<EntityPickerLabels>;
|
|
84
140
|
tree?: Partial<TreeLabels>;
|
|
85
141
|
/** `OrgChart` (HAR-1807): loading and error rows, the report count, the zoom toolbar. */
|
|
86
142
|
orgChart?: Partial<OrgChartLabels>;
|
|
87
143
|
inlineEdit?: Partial<InlineEditLabels>;
|
|
144
|
+
/** `SortableList` (HAR-1375): the grip, Move up / Move down, the move announcement. */
|
|
145
|
+
sortableList?: Partial<SortableListLabels>;
|
|
146
|
+
/** `typeToConfirmMismatch` (HAR-1831): `{value}` is the text to type. */
|
|
88
147
|
confirmDialog?: {
|
|
89
148
|
typeToConfirm?: string;
|
|
90
149
|
compensation?: string;
|
|
150
|
+
typeToConfirmMismatch?: string;
|
|
91
151
|
};
|
|
92
152
|
schedulingCalendar?: Partial<SchedulingCalendarLabels>;
|
|
93
153
|
dateRangePicker?: Partial<DateRangePickerLabels>;
|
|
94
154
|
datePicker?: Partial<DatePickerLabels>;
|
|
95
155
|
dateTimePicker?: Partial<DateTimePickerLabels>;
|
|
156
|
+
/** `TimePicker` (HAR-1835), also the time part of `DateTimePicker`. */
|
|
157
|
+
timePicker?: Partial<TimePickerLabels>;
|
|
96
158
|
schedulingTimeline?: Partial<SchedulingTimelineLabels>;
|
|
97
159
|
textDiff?: Partial<TextDiffLabels>;
|
|
160
|
+
/** `DiffViewer` (HAR-1369): the version names, the resolution buttons, the summary. */
|
|
161
|
+
diffViewer?: Partial<DiffViewerLabels>;
|
|
162
|
+
/** `MatchReview` (HAR-1369): the decision table, bulk actions and the adopt mode. */
|
|
163
|
+
matchReview?: Partial<MatchReviewLabels>;
|
|
164
|
+
/** `AuditLog` (HAR-987): the filters, Details, Show older entries, and every state. */
|
|
165
|
+
auditLog?: Partial<AuditLogLabels>;
|
|
166
|
+
/** `DataWorkspace` (HAR-1388): the toolbar, selection, footer and states. */
|
|
167
|
+
dataWorkspace?: Partial<DataWorkspaceLabels>;
|
|
98
168
|
filterEditor?: Partial<FilterEditorLabels>;
|
|
99
169
|
select?: Partial<SelectLabels>;
|
|
100
170
|
ruleBuilder?: Partial<RuleBuilderLabels>;
|
|
101
171
|
fileUpload?: Partial<FileUploadLabels>;
|
|
102
172
|
attachment?: Partial<AttachmentLabels>;
|
|
173
|
+
/** `TagInput` (HAR-1377): the chips' × names, the announcements and the refusals. */
|
|
174
|
+
tagInput?: Partial<TagInputLabels>;
|
|
175
|
+
/** `PasswordInput` (HAR-1376): the reveal toggle's name. */
|
|
176
|
+
passwordInput?: Partial<PasswordInputLabels>;
|
|
103
177
|
/** `remove`: the name of a removable chip's × button; `{label}` is the chip text. */
|
|
104
178
|
chip?: {
|
|
105
179
|
remove?: string;
|
|
@@ -108,6 +182,8 @@ interface UixLabels {
|
|
|
108
182
|
alert?: {
|
|
109
183
|
dismiss?: string;
|
|
110
184
|
};
|
|
185
|
+
/** Not words: the date format of every date field (HAR-2432). See {@link UixDateFormat}. */
|
|
186
|
+
dateFormat?: UixDateFormat;
|
|
111
187
|
/** Read by `useUixLabels()` callers; `Pagination` itself is server-safe and takes `labels`. */
|
|
112
188
|
pagination?: Partial<PaginationLabels>;
|
|
113
189
|
/** Read by `useUixLabels()` callers; `BulkBar` itself is server-safe and takes `label`. */
|
|
@@ -115,6 +191,20 @@ interface UixLabels {
|
|
|
115
191
|
region?: string;
|
|
116
192
|
};
|
|
117
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* One date format for every date field below the provider (HAR-2432): `DatePicker`,
|
|
196
|
+
* `DateTimePicker`, `DateRangePicker` and `TimePicker` (its `locale`). Each field's own prop wins.
|
|
197
|
+
*/
|
|
198
|
+
interface UixDateFormat {
|
|
199
|
+
/** The locale of the field's text, month and weekday names, and the clock. */
|
|
200
|
+
locale?: string;
|
|
201
|
+
/** How a field writes a `YYYY-MM-DD` date, e.g. `(d) => d.split('-').reverse().join('.')`. */
|
|
202
|
+
formatDate?: (date: string) => string;
|
|
203
|
+
/** Read typed text into `YYYY-MM-DD`, or `null` when it is not a date. Pass it with `formatDate`. */
|
|
204
|
+
parseDate?: (text: string) => string | null;
|
|
205
|
+
/** The date field's placeholder, e.g. `TT.MM.JJJJ`. */
|
|
206
|
+
placeholder?: string;
|
|
207
|
+
}
|
|
118
208
|
interface UixLabelsProviderProps {
|
|
119
209
|
labels: UixLabels;
|
|
120
210
|
children?: ReactNode;
|
|
@@ -124,4 +214,4 @@ declare function UixLabelsProvider({ labels, children }: UixLabelsProviderProps)
|
|
|
124
214
|
/** The chrome strings in effect here (empty outside a provider). */
|
|
125
215
|
declare function useUixLabels(): UixLabels;
|
|
126
216
|
|
|
127
|
-
export { type UixLabels, UixLabelsProvider, type UixLabelsProviderProps, useUixLabels };
|
|
217
|
+
export { type UixDateFormat, type UixLabels, UixLabelsProvider, type UixLabelsProviderProps, useUixLabels };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Under this, a pending action shows nothing new: a spinner that would flash for 150 ms is noise. */
|
|
2
|
+
declare const PENDING_DELAY_MS = 300;
|
|
3
|
+
/** Once a pending indicator appears, it stays at least this long so it never flickers. */
|
|
4
|
+
declare const PENDING_MIN_VISIBLE_MS = 500;
|
|
5
|
+
/** How long an in-place result ("Saved", "Couldn't save") holds before the control returns. */
|
|
6
|
+
declare const RESULT_HOLD_MS = 1500;
|
|
7
|
+
|
|
8
|
+
export { PENDING_DELAY_MS, PENDING_MIN_VISIBLE_MS, RESULT_HOLD_MS };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Register an open overlay; the returned function removes it (call it when it closes). */
|
|
2
|
+
declare function pushLayer(token: object): () => void;
|
|
3
|
+
/** Whether `token` is the newest open overlay. */
|
|
4
|
+
declare const isTopLayer: (token: object) => boolean;
|
|
5
|
+
|
|
6
|
+
export { isTopLayer, pushLayer };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const layers = [];
|
|
2
|
+
function pushLayer(token) {
|
|
3
|
+
layers.push(token);
|
|
4
|
+
return () => {
|
|
5
|
+
const i = layers.lastIndexOf(token);
|
|
6
|
+
if (i >= 0) layers.splice(i, 1);
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
const isTopLayer = (token) => layers[layers.length - 1] === token;
|
|
10
|
+
export {
|
|
11
|
+
isTopLayer,
|
|
12
|
+
pushLayer
|
|
13
|
+
};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A QR Code encoder (ISO/IEC 18004) for `QrCode` (HAR-1251): byte mode (UTF-8), the four
|
|
3
|
+
* error-correction levels, versions 1 to 40, all eight masks scored by the standard's
|
|
4
|
+
* penalty rules. Pure and dependency-free, so a consumer never pulls a QR library in for a
|
|
5
|
+
* poster or a voucher. `qr-model.test.mjs` decodes its output with a reference decoder.
|
|
6
|
+
*
|
|
7
|
+
* The algorithm follows the standard's own construction (function patterns, Reed-Solomon over
|
|
8
|
+
* GF(256) with 0x11D, zig-zag placement, BCH-coded format and version information).
|
|
9
|
+
*/
|
|
10
|
+
/** How much of the symbol can be lost and still read: about 7, 15, 25 and 30 % of codewords. */
|
|
11
|
+
type QrErrorCorrection = 'L' | 'M' | 'Q' | 'H';
|
|
12
|
+
interface QrMatrix {
|
|
13
|
+
/** 1 to 40. Each version is 4 modules wider than the one before (version 1 is 21 × 21). */
|
|
14
|
+
version: number;
|
|
15
|
+
/** Modules per side, without the quiet zone. */
|
|
16
|
+
size: number;
|
|
17
|
+
errorCorrection: QrErrorCorrection;
|
|
18
|
+
/** The mask the penalty rules chose, 0 to 7. */
|
|
19
|
+
mask: number;
|
|
20
|
+
/** `modules[y][x]` is true for a dark module. */
|
|
21
|
+
modules: boolean[][];
|
|
22
|
+
}
|
|
23
|
+
interface QrEncodeOptions {
|
|
24
|
+
/** Default `M`: survives a crease or a smudge on a printed poster. */
|
|
25
|
+
errorCorrection?: QrErrorCorrection;
|
|
26
|
+
/**
|
|
27
|
+
* The smallest version to use (1 to 40); a larger one is chosen when the text needs it. A
|
|
28
|
+
* value that is not a finite number throws a `RangeError` (it is a mistake, not a long text).
|
|
29
|
+
*/
|
|
30
|
+
minVersion?: number;
|
|
31
|
+
/**
|
|
32
|
+
* Mark text with characters beyond ASCII as UTF-8 with an ECI 26 designator (12 bits before
|
|
33
|
+
* the data). Off by default: most scanners read UTF-8 without it and a few old ones misread a
|
|
34
|
+
* symbol that has one; turn it on for a scanner that assumes ISO 8859-1 otherwise.
|
|
35
|
+
*/
|
|
36
|
+
eci?: boolean;
|
|
37
|
+
/** Force a mask (0 to 7) instead of the lowest-penalty one; for tests. */
|
|
38
|
+
mask?: number;
|
|
39
|
+
}
|
|
40
|
+
/** Thrown when the text does not fit in version 40 at the requested level. */
|
|
41
|
+
declare class QrCapacityError extends Error {
|
|
42
|
+
readonly bytes: number;
|
|
43
|
+
readonly errorCorrection: QrErrorCorrection;
|
|
44
|
+
constructor(bytes: number, errorCorrection: QrErrorCorrection);
|
|
45
|
+
}
|
|
46
|
+
/** Data codewords (bytes) a version holds at a level. */
|
|
47
|
+
declare function qrDataCapacity(version: number, errorCorrection: QrErrorCorrection): number;
|
|
48
|
+
/**
|
|
49
|
+
* The smallest version that holds `bytes` bytes at a level, or undefined past version 40.
|
|
50
|
+
* `headerBits` counts bits before the byte segment (12 for an ECI designator).
|
|
51
|
+
*/
|
|
52
|
+
declare function qrVersionFor(bytes: number, errorCorrection: QrErrorCorrection, minVersion?: number, headerBits?: number): number | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Encodes `text` (as UTF-8 bytes) into a QR matrix: the smallest version that fits at the
|
|
55
|
+
* level, the mask with the lowest penalty. Throws `QrCapacityError` past version 40
|
|
56
|
+
* (2,953 bytes at L, 1,273 at H).
|
|
57
|
+
*/
|
|
58
|
+
declare function encodeQr(text: string, options?: QrEncodeOptions): QrMatrix;
|
|
59
|
+
/**
|
|
60
|
+
* The dark modules as one SVG path in module units, offset by `margin` (the quiet zone):
|
|
61
|
+
* one `h`-run per stretch of dark modules in a row, so a version-10 symbol is one short path.
|
|
62
|
+
*/
|
|
63
|
+
declare function qrPath(matrix: QrMatrix, margin?: number): string;
|
|
64
|
+
|
|
65
|
+
export { QrCapacityError, type QrEncodeOptions, type QrErrorCorrection, type QrMatrix, encodeQr, qrDataCapacity, qrPath, qrVersionFor };
|
package/dist/qr-model.js
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
class QrCapacityError extends Error {
|
|
2
|
+
constructor(bytes, errorCorrection) {
|
|
3
|
+
super(`QR: ${bytes} bytes do not fit in version 40 at error correction ${errorCorrection}`);
|
|
4
|
+
this.name = "QrCapacityError";
|
|
5
|
+
this.bytes = bytes;
|
|
6
|
+
this.errorCorrection = errorCorrection;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
const LEVEL_INDEX = { L: 0, M: 1, Q: 2, H: 3 };
|
|
10
|
+
const FORMAT_BITS = { L: 1, M: 0, Q: 3, H: 2 };
|
|
11
|
+
const ECC_PER_BLOCK = [
|
|
12
|
+
[-1, 7, 10, 15, 20, 26, 18, 20, 24, 30, 18, 20, 24, 26, 30, 22, 24, 28, 30, 28, 28, 28, 28, 30, 30, 26, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
|
|
13
|
+
[-1, 10, 16, 26, 18, 24, 16, 18, 22, 22, 26, 30, 22, 22, 24, 24, 28, 28, 26, 26, 26, 26, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28],
|
|
14
|
+
[-1, 13, 22, 18, 26, 18, 24, 18, 22, 20, 24, 28, 26, 24, 20, 30, 24, 28, 28, 26, 30, 28, 30, 30, 30, 30, 28, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30],
|
|
15
|
+
[-1, 17, 28, 22, 16, 22, 28, 26, 26, 24, 28, 24, 28, 22, 24, 24, 30, 28, 28, 26, 28, 30, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30]
|
|
16
|
+
];
|
|
17
|
+
const BLOCKS = [
|
|
18
|
+
[-1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 4, 4, 4, 4, 4, 6, 6, 6, 6, 7, 8, 8, 9, 9, 10, 12, 12, 12, 13, 14, 15, 16, 17, 18, 19, 19, 20, 21, 22, 24, 25],
|
|
19
|
+
[-1, 1, 1, 1, 2, 2, 4, 4, 4, 5, 5, 5, 8, 9, 9, 10, 10, 11, 13, 14, 16, 17, 17, 18, 20, 21, 23, 25, 26, 28, 29, 31, 33, 35, 37, 38, 40, 43, 45, 47, 49],
|
|
20
|
+
[-1, 1, 1, 2, 2, 4, 4, 6, 6, 8, 8, 8, 10, 12, 16, 12, 17, 16, 18, 21, 20, 23, 23, 25, 27, 29, 34, 34, 35, 38, 40, 43, 45, 48, 51, 53, 56, 59, 62, 65, 68],
|
|
21
|
+
[-1, 1, 1, 2, 4, 4, 4, 5, 6, 8, 8, 11, 11, 16, 16, 18, 16, 19, 21, 25, 25, 25, 34, 30, 32, 35, 37, 40, 42, 45, 48, 51, 54, 57, 60, 63, 66, 70, 74, 77, 81]
|
|
22
|
+
];
|
|
23
|
+
function rawDataModules(version) {
|
|
24
|
+
let result = (16 * version + 128) * version + 64;
|
|
25
|
+
if (version >= 2) {
|
|
26
|
+
const align = Math.floor(version / 7) + 2;
|
|
27
|
+
result -= (25 * align - 10) * align - 55;
|
|
28
|
+
if (version >= 7) result -= 36;
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
function qrDataCapacity(version, errorCorrection) {
|
|
33
|
+
const level = LEVEL_INDEX[errorCorrection];
|
|
34
|
+
return Math.floor(rawDataModules(version) / 8) - ECC_PER_BLOCK[level][version] * BLOCKS[level][version];
|
|
35
|
+
}
|
|
36
|
+
const segmentBits = (bytes, version) => 4 + (version <= 9 ? 8 : 16) + bytes * 8;
|
|
37
|
+
const ECI_UTF8_BITS = 12;
|
|
38
|
+
function qrVersionFor(bytes, errorCorrection, minVersion = 1, headerBits = 0) {
|
|
39
|
+
if (!Number.isFinite(minVersion)) throw new RangeError(`QR: minVersion must be a number from 1 to 40, not ${minVersion}`);
|
|
40
|
+
for (let version = Math.max(1, Math.min(40, Math.floor(minVersion))); version <= 40; version += 1) {
|
|
41
|
+
if (bytes < (version <= 9 ? 256 : 65536) && headerBits + segmentBits(bytes, version) <= qrDataCapacity(version, errorCorrection) * 8) return version;
|
|
42
|
+
}
|
|
43
|
+
return void 0;
|
|
44
|
+
}
|
|
45
|
+
function gfMultiply(x, y) {
|
|
46
|
+
let z = 0;
|
|
47
|
+
for (let i = 7; i >= 0; i -= 1) {
|
|
48
|
+
z = z << 1 ^ (z >>> 7) * 285;
|
|
49
|
+
z ^= (y >>> i & 1) * x;
|
|
50
|
+
}
|
|
51
|
+
return z;
|
|
52
|
+
}
|
|
53
|
+
function rsDivisor(degree) {
|
|
54
|
+
const result = new Array(degree).fill(0);
|
|
55
|
+
result[degree - 1] = 1;
|
|
56
|
+
let root = 1;
|
|
57
|
+
for (let i = 0; i < degree; i += 1) {
|
|
58
|
+
for (let j = 0; j < result.length; j += 1) {
|
|
59
|
+
result[j] = gfMultiply(result[j], root);
|
|
60
|
+
if (j + 1 < result.length) result[j] ^= result[j + 1];
|
|
61
|
+
}
|
|
62
|
+
root = gfMultiply(root, 2);
|
|
63
|
+
}
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
function rsRemainder(data, divisor) {
|
|
67
|
+
const result = divisor.map(() => 0);
|
|
68
|
+
for (const byte of data) {
|
|
69
|
+
const factor = byte ^ result.shift();
|
|
70
|
+
result.push(0);
|
|
71
|
+
divisor.forEach((coefficient, i) => {
|
|
72
|
+
result[i] ^= gfMultiply(coefficient, factor);
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
function withErrorCorrection(data, version, errorCorrection) {
|
|
78
|
+
const level = LEVEL_INDEX[errorCorrection];
|
|
79
|
+
const blockCount = BLOCKS[level][version];
|
|
80
|
+
const eccLength = ECC_PER_BLOCK[level][version];
|
|
81
|
+
const rawCodewords = Math.floor(rawDataModules(version) / 8);
|
|
82
|
+
const shortBlocks = blockCount - rawCodewords % blockCount;
|
|
83
|
+
const shortLength = Math.floor(rawCodewords / blockCount);
|
|
84
|
+
const divisor = rsDivisor(eccLength);
|
|
85
|
+
const blocks = [];
|
|
86
|
+
for (let i = 0, k = 0; i < blockCount; i += 1) {
|
|
87
|
+
const block = data.slice(k, k + shortLength - eccLength + (i < shortBlocks ? 0 : 1));
|
|
88
|
+
k += block.length;
|
|
89
|
+
const ecc = rsRemainder(block, divisor);
|
|
90
|
+
if (i < shortBlocks) block.push(0);
|
|
91
|
+
blocks.push(block.concat(ecc));
|
|
92
|
+
}
|
|
93
|
+
const result = [];
|
|
94
|
+
for (let i = 0; i < blocks[0].length; i += 1) {
|
|
95
|
+
blocks.forEach((block, j) => {
|
|
96
|
+
if (i !== shortLength - eccLength || j >= shortBlocks) result.push(block[i]);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
}
|
|
101
|
+
function dataCodewords(bytes, version, errorCorrection, eci) {
|
|
102
|
+
const bits = [];
|
|
103
|
+
const append = (value, length) => {
|
|
104
|
+
for (let i = length - 1; i >= 0; i -= 1) bits.push(value >>> i & 1);
|
|
105
|
+
};
|
|
106
|
+
if (eci) {
|
|
107
|
+
append(7, 4);
|
|
108
|
+
append(26, 8);
|
|
109
|
+
}
|
|
110
|
+
append(4, 4);
|
|
111
|
+
append(bytes.length, version <= 9 ? 8 : 16);
|
|
112
|
+
for (const byte of bytes) append(byte, 8);
|
|
113
|
+
const capacity = qrDataCapacity(version, errorCorrection) * 8;
|
|
114
|
+
append(0, Math.min(4, capacity - bits.length));
|
|
115
|
+
append(0, (8 - bits.length % 8) % 8);
|
|
116
|
+
for (let pad = 236; bits.length < capacity; pad ^= 236 ^ 17) append(pad, 8);
|
|
117
|
+
const codewords = [];
|
|
118
|
+
for (let i = 0; i < bits.length; i += 8) codewords.push(bits.slice(i, i + 8).reduce((byte, bit) => byte << 1 | bit, 0));
|
|
119
|
+
return codewords;
|
|
120
|
+
}
|
|
121
|
+
function alignmentPositions(version) {
|
|
122
|
+
if (version === 1) return [];
|
|
123
|
+
const count = Math.floor(version / 7) + 2;
|
|
124
|
+
const step = Math.floor((version * 8 + count * 3 + 5) / (count * 4 - 4)) * 2;
|
|
125
|
+
const result = [6];
|
|
126
|
+
for (let position = version * 4 + 17 - 7; result.length < count; position -= step) result.splice(1, 0, position);
|
|
127
|
+
return result;
|
|
128
|
+
}
|
|
129
|
+
const MASKS = [
|
|
130
|
+
(x, y) => (x + y) % 2 === 0,
|
|
131
|
+
(_x, y) => y % 2 === 0,
|
|
132
|
+
(x) => x % 3 === 0,
|
|
133
|
+
(x, y) => (x + y) % 3 === 0,
|
|
134
|
+
(x, y) => (Math.floor(x / 3) + Math.floor(y / 2)) % 2 === 0,
|
|
135
|
+
(x, y) => x * y % 2 + x * y % 3 === 0,
|
|
136
|
+
(x, y) => (x * y % 2 + x * y % 3) % 2 === 0,
|
|
137
|
+
(x, y) => ((x + y) % 2 + x * y % 3) % 2 === 0
|
|
138
|
+
];
|
|
139
|
+
class QrSymbol {
|
|
140
|
+
constructor(version, errorCorrection) {
|
|
141
|
+
this.version = version;
|
|
142
|
+
this.errorCorrection = errorCorrection;
|
|
143
|
+
this.size = version * 4 + 17;
|
|
144
|
+
this.modules = Array.from({ length: this.size }, () => new Array(this.size).fill(false));
|
|
145
|
+
this.reserved = Array.from({ length: this.size }, () => new Array(this.size).fill(false));
|
|
146
|
+
this.drawFunctionPatterns();
|
|
147
|
+
}
|
|
148
|
+
set(x, y, dark) {
|
|
149
|
+
this.modules[y][x] = dark;
|
|
150
|
+
this.reserved[y][x] = true;
|
|
151
|
+
}
|
|
152
|
+
drawFunctionPatterns() {
|
|
153
|
+
const { size } = this;
|
|
154
|
+
for (let i = 0; i < size; i += 1) {
|
|
155
|
+
this.set(6, i, i % 2 === 0);
|
|
156
|
+
this.set(i, 6, i % 2 === 0);
|
|
157
|
+
}
|
|
158
|
+
for (const [cx, cy] of [[3, 3], [size - 4, 3], [3, size - 4]]) {
|
|
159
|
+
for (let dy = -4; dy <= 4; dy += 1) {
|
|
160
|
+
for (let dx = -4; dx <= 4; dx += 1) {
|
|
161
|
+
const x = cx + dx;
|
|
162
|
+
const y = cy + dy;
|
|
163
|
+
if (x < 0 || x >= size || y < 0 || y >= size) continue;
|
|
164
|
+
const ring = Math.max(Math.abs(dx), Math.abs(dy));
|
|
165
|
+
this.set(x, y, ring !== 2 && ring !== 4);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const positions = alignmentPositions(this.version);
|
|
170
|
+
const last = positions.length - 1;
|
|
171
|
+
positions.forEach((cx, i) => positions.forEach((cy, j) => {
|
|
172
|
+
if (i === 0 && j === 0 || i === 0 && j === last || i === last && j === 0) return;
|
|
173
|
+
for (let dy = -2; dy <= 2; dy += 1) {
|
|
174
|
+
for (let dx = -2; dx <= 2; dx += 1) this.set(cx + dx, cy + dy, Math.max(Math.abs(dx), Math.abs(dy)) !== 1);
|
|
175
|
+
}
|
|
176
|
+
}));
|
|
177
|
+
this.drawFormat(0);
|
|
178
|
+
this.drawVersion();
|
|
179
|
+
}
|
|
180
|
+
drawFormat(mask) {
|
|
181
|
+
const data = FORMAT_BITS[this.errorCorrection] << 3 | mask;
|
|
182
|
+
let remainder = data;
|
|
183
|
+
for (let i = 0; i < 10; i += 1) remainder = remainder << 1 ^ (remainder >>> 9) * 1335;
|
|
184
|
+
const bits = (data << 10 | remainder) ^ 21522;
|
|
185
|
+
const bit = (i) => (bits >>> i & 1) !== 0;
|
|
186
|
+
const { size } = this;
|
|
187
|
+
for (let i = 0; i <= 5; i += 1) this.set(8, i, bit(i));
|
|
188
|
+
this.set(8, 7, bit(6));
|
|
189
|
+
this.set(8, 8, bit(7));
|
|
190
|
+
this.set(7, 8, bit(8));
|
|
191
|
+
for (let i = 9; i < 15; i += 1) this.set(14 - i, 8, bit(i));
|
|
192
|
+
for (let i = 0; i < 8; i += 1) this.set(size - 1 - i, 8, bit(i));
|
|
193
|
+
for (let i = 8; i < 15; i += 1) this.set(8, size - 15 + i, bit(i));
|
|
194
|
+
this.set(8, size - 8, true);
|
|
195
|
+
}
|
|
196
|
+
drawVersion() {
|
|
197
|
+
if (this.version < 7) return;
|
|
198
|
+
let remainder = this.version;
|
|
199
|
+
for (let i = 0; i < 12; i += 1) remainder = remainder << 1 ^ (remainder >>> 11) * 7973;
|
|
200
|
+
const bits = this.version << 12 | remainder;
|
|
201
|
+
for (let i = 0; i < 18; i += 1) {
|
|
202
|
+
const dark = (bits >>> i & 1) !== 0;
|
|
203
|
+
const a = this.size - 11 + i % 3;
|
|
204
|
+
const b = Math.floor(i / 3);
|
|
205
|
+
this.set(a, b, dark);
|
|
206
|
+
this.set(b, a, dark);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
drawCodewords(codewords) {
|
|
210
|
+
const { size } = this;
|
|
211
|
+
let i = 0;
|
|
212
|
+
for (let right = size - 1; right >= 1; right -= 2) {
|
|
213
|
+
if (right === 6) right = 5;
|
|
214
|
+
for (let vertical = 0; vertical < size; vertical += 1) {
|
|
215
|
+
for (let j = 0; j < 2; j += 1) {
|
|
216
|
+
const x = right - j;
|
|
217
|
+
const upward = (right + 1 & 2) === 0;
|
|
218
|
+
const y = upward ? size - 1 - vertical : vertical;
|
|
219
|
+
if (this.reserved[y][x] || i >= codewords.length * 8) continue;
|
|
220
|
+
this.modules[y][x] = (codewords[i >>> 3] >>> 7 - (i & 7) & 1) !== 0;
|
|
221
|
+
i += 1;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
/** XORs a mask over the data modules; applying it twice undoes it. */
|
|
227
|
+
applyMask(mask) {
|
|
228
|
+
const flip = MASKS[mask];
|
|
229
|
+
for (let y = 0; y < this.size; y += 1) {
|
|
230
|
+
for (let x = 0; x < this.size; x += 1) {
|
|
231
|
+
if (!this.reserved[y][x] && flip(x, y)) this.modules[y][x] = !this.modules[y][x];
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/** The standard's four penalty rules: runs, 2 × 2 blocks, finder look-alikes, dark balance. */
|
|
236
|
+
penalty() {
|
|
237
|
+
const { size, modules } = this;
|
|
238
|
+
let score = 0;
|
|
239
|
+
const line = (get) => {
|
|
240
|
+
let run = 1;
|
|
241
|
+
for (let i = 1; i <= size; i += 1) {
|
|
242
|
+
if (i < size && get(i) === get(i - 1)) {
|
|
243
|
+
run += 1;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (run >= 5) score += 3 + (run - 5);
|
|
247
|
+
run = 1;
|
|
248
|
+
}
|
|
249
|
+
for (let i = 0; i + 11 <= size; i += 1) {
|
|
250
|
+
const window = Array.from({ length: 11 }, (_, k) => get(i + k));
|
|
251
|
+
const core = window[4] && !window[5] && window[6] && window[7] && window[8] && !window[9] && window[10];
|
|
252
|
+
const coreReverse = window[0] && !window[1] && window[2] && window[3] && window[4] && !window[5] && window[6];
|
|
253
|
+
if (core && !window[0] && !window[1] && !window[2] && !window[3]) score += 40;
|
|
254
|
+
if (coreReverse && !window[7] && !window[8] && !window[9] && !window[10]) score += 40;
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
for (let y = 0; y < size; y += 1) line((x) => modules[y][x]);
|
|
258
|
+
for (let x = 0; x < size; x += 1) line((y) => modules[y][x]);
|
|
259
|
+
let dark = 0;
|
|
260
|
+
for (let y = 0; y < size; y += 1) {
|
|
261
|
+
for (let x = 0; x < size; x += 1) {
|
|
262
|
+
const value = modules[y][x];
|
|
263
|
+
if (value) dark += 1;
|
|
264
|
+
if (x + 1 < size && y + 1 < size && value === modules[y][x + 1] && value === modules[y + 1][x] && value === modules[y + 1][x + 1]) score += 3;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const total = size * size;
|
|
268
|
+
score += (Math.ceil(Math.abs(dark * 20 - total * 10) / total) - 1) * 10;
|
|
269
|
+
return score;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function utf8(text) {
|
|
273
|
+
if (typeof TextEncoder !== "undefined") return new TextEncoder().encode(text);
|
|
274
|
+
const escaped = unescape(encodeURIComponent(text));
|
|
275
|
+
return Uint8Array.from(escaped, (c) => c.charCodeAt(0));
|
|
276
|
+
}
|
|
277
|
+
function encodeQr(text, options = {}) {
|
|
278
|
+
const errorCorrection = options.errorCorrection ?? "M";
|
|
279
|
+
const bytes = utf8(text);
|
|
280
|
+
const eci = options.eci === true && bytes.some((byte) => byte >= 128);
|
|
281
|
+
const version = qrVersionFor(bytes.length, errorCorrection, options.minVersion ?? 1, eci ? ECI_UTF8_BITS : 0);
|
|
282
|
+
if (version === void 0) throw new QrCapacityError(bytes.length, errorCorrection);
|
|
283
|
+
const symbol = new QrSymbol(version, errorCorrection);
|
|
284
|
+
symbol.drawCodewords(withErrorCorrection(dataCodewords(bytes, version, errorCorrection, eci), version, errorCorrection));
|
|
285
|
+
let mask = options.mask;
|
|
286
|
+
if (mask === void 0) {
|
|
287
|
+
let best = Infinity;
|
|
288
|
+
for (let candidate = 0; candidate < 8; candidate += 1) {
|
|
289
|
+
symbol.applyMask(candidate);
|
|
290
|
+
symbol.drawFormat(candidate);
|
|
291
|
+
const score = symbol.penalty();
|
|
292
|
+
if (score < best) {
|
|
293
|
+
best = score;
|
|
294
|
+
mask = candidate;
|
|
295
|
+
}
|
|
296
|
+
symbol.applyMask(candidate);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
symbol.applyMask(mask);
|
|
300
|
+
symbol.drawFormat(mask);
|
|
301
|
+
return { version, size: symbol.size, errorCorrection, mask, modules: symbol.modules };
|
|
302
|
+
}
|
|
303
|
+
function qrPath(matrix, margin = 4) {
|
|
304
|
+
const parts = [];
|
|
305
|
+
matrix.modules.forEach((row, y) => {
|
|
306
|
+
for (let x = 0; x < row.length; x += 1) {
|
|
307
|
+
if (!row[x]) continue;
|
|
308
|
+
let end = x;
|
|
309
|
+
while (end + 1 < row.length && row[end + 1]) end += 1;
|
|
310
|
+
const length = end - x + 1;
|
|
311
|
+
parts.push(`M${x + margin} ${y + margin}h${length}v1h-${length}z`);
|
|
312
|
+
x = end;
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
return parts.join("");
|
|
316
|
+
}
|
|
317
|
+
export {
|
|
318
|
+
QrCapacityError,
|
|
319
|
+
encodeQr,
|
|
320
|
+
qrDataCapacity,
|
|
321
|
+
qrPath,
|
|
322
|
+
qrVersionFor
|
|
323
|
+
};
|