@particle-academy/react-fancy 6.7.1 → 6.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.
- package/CHANGELOG.md +19 -0
- package/dist/{chunk-AE53RKWR.cjs → chunk-CNWTYRZC.cjs} +407 -22
- package/dist/chunk-CNWTYRZC.cjs.map +1 -0
- package/dist/{chunk-B6WTCAGY.js → chunk-PDVU2PXR.js} +97 -53
- package/dist/chunk-PDVU2PXR.js.map +1 -0
- package/dist/{chunk-RLE5WYY6.js → chunk-PIG3UTHU.js} +406 -24
- package/dist/chunk-PIG3UTHU.js.map +1 -0
- package/dist/{chunk-OUNGGQIS.cjs → chunk-VZTXUYPM.cjs} +97 -53
- package/dist/chunk-VZTXUYPM.cjs.map +1 -0
- package/dist/index.cjs +23 -11
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/prompt-input.cjs +4 -4
- package/dist/prompt-input.js +1 -1
- package/dist/qr-code.cjs +19 -4
- package/dist/qr-code.d.cts +221 -2
- package/dist/qr-code.d.ts +221 -2
- package/dist/qr-code.js +4 -1
- package/docs/PromptInput.md +10 -2
- package/docs/QrCode.md +108 -0
- package/package.json +1 -1
- package/dist/chunk-AE53RKWR.cjs.map +0 -1
- package/dist/chunk-B6WTCAGY.js.map +0 -1
- package/dist/chunk-OUNGGQIS.cjs.map +0 -1
- package/dist/chunk-RLE5WYY6.js.map +0 -1
package/dist/qr-code.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { SVGAttributes } from 'react';
|
|
2
|
+
import { SVGAttributes, HTMLAttributes } from 'react';
|
|
3
|
+
import { S as Size } from './types-DJI492iY.cjs';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* ISO/IEC 18004 table data for the QR encoder. **Data, not logic** — kept in
|
|
@@ -220,4 +221,222 @@ interface QrCodeProps extends Omit<SVGAttributes<SVGSVGElement>, "children" | "v
|
|
|
220
221
|
*/
|
|
221
222
|
declare const QrCode: react.ForwardRefExoticComponent<QrCodeProps & react.RefAttributes<SVGSVGElement>>;
|
|
222
223
|
|
|
223
|
-
|
|
224
|
+
/** What a person can do with a code. Each renders one `Button`. */
|
|
225
|
+
type QrCodeAction = "download-svg" | "download-png" | "share" | "print";
|
|
226
|
+
/**
|
|
227
|
+
* How an action ended.
|
|
228
|
+
*
|
|
229
|
+
* - `done`: the file was handed to the browser, the share sheet completed, the
|
|
230
|
+
* value was copied, or the print dialog was opened.
|
|
231
|
+
* - `cancelled`: the person dismissed the share sheet. Not an error.
|
|
232
|
+
* - `failed`: nothing happened that the person asked for; `error` says why.
|
|
233
|
+
*/
|
|
234
|
+
type QrCodeActionOutcome = "done" | "cancelled" | "failed";
|
|
235
|
+
/** One action, reported. Plain JSON, so it can go straight to an agent or a log. */
|
|
236
|
+
interface QrCodeActionEvent {
|
|
237
|
+
action: QrCodeAction;
|
|
238
|
+
outcome: QrCodeActionOutcome;
|
|
239
|
+
/** For `share`: whether the Web Share sheet or the clipboard carried it. */
|
|
240
|
+
via?: "share" | "clipboard";
|
|
241
|
+
/** For a download: the file name the browser was given. */
|
|
242
|
+
fileName?: string;
|
|
243
|
+
/** For `failed`: the reason, as text. */
|
|
244
|
+
error?: string;
|
|
245
|
+
}
|
|
246
|
+
/** Visible button text and the announcements read out after each action. */
|
|
247
|
+
interface QrCodePanelLabels {
|
|
248
|
+
downloadSvg: string;
|
|
249
|
+
downloadPng: string;
|
|
250
|
+
share: string;
|
|
251
|
+
/** The share button's text where Web Share is absent and a web link is copied. */
|
|
252
|
+
copyLink: string;
|
|
253
|
+
/** The same, for a value that is not a web link. */
|
|
254
|
+
copy: string;
|
|
255
|
+
print: string;
|
|
256
|
+
downloaded: string;
|
|
257
|
+
shared: string;
|
|
258
|
+
copied: string;
|
|
259
|
+
printing: string;
|
|
260
|
+
failed: string;
|
|
261
|
+
}
|
|
262
|
+
interface QrCodePanelProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "onChange"> {
|
|
263
|
+
/** What the code carries. Any string; see `QrCode`'s `value`. */
|
|
264
|
+
value: string;
|
|
265
|
+
/**
|
|
266
|
+
* What the code is FOR, e.g. "Your sign-up link". Required. Names the code,
|
|
267
|
+
* the group around it, the SVG file's `<title>`, the print page's title,
|
|
268
|
+
* and the share sheet's title unless `shareTitle` is set.
|
|
269
|
+
*/
|
|
270
|
+
label: string;
|
|
271
|
+
/** Rendered size of the code in pixels. Default 192. */
|
|
272
|
+
size?: number;
|
|
273
|
+
errorCorrection?: QrErrorCorrection;
|
|
274
|
+
quietZone?: number;
|
|
275
|
+
/**
|
|
276
|
+
* Module colour. Default `#000000`, on screen as well as in files.
|
|
277
|
+
*
|
|
278
|
+
* The panel does NOT inherit text colour the way a bare `<QrCode>` does: a
|
|
279
|
+
* code must be dark on light to scan, so the panel pins black on white in
|
|
280
|
+
* dark mode too. Black on white is 21:1, past WCAG AAA's 7:1.
|
|
281
|
+
*/
|
|
282
|
+
foreground?: string;
|
|
283
|
+
/** Background, quiet zone included. Default `#ffffff`, in both colour schemes. */
|
|
284
|
+
background?: string;
|
|
285
|
+
mode?: QrMode;
|
|
286
|
+
version?: number;
|
|
287
|
+
/**
|
|
288
|
+
* Which actions to offer, in order. Default all four:
|
|
289
|
+
* `["download-svg", "download-png", "share", "print"]`. `[]` renders none.
|
|
290
|
+
*/
|
|
291
|
+
actions?: readonly QrCodeAction[];
|
|
292
|
+
/**
|
|
293
|
+
* Show the value as selectable text under the code, and on the printed page.
|
|
294
|
+
* Default `false`, because not every value is meant to be read out: a WiFi
|
|
295
|
+
* block carries a password. Turn it on for a link or a reference a person
|
|
296
|
+
* might type instead of scanning.
|
|
297
|
+
*/
|
|
298
|
+
showValue?: boolean;
|
|
299
|
+
/** Download file name, without extension. Sanitised. Default `"qr-code"`. */
|
|
300
|
+
fileName?: string;
|
|
301
|
+
/** PNG pixels per module, a whole number. Default 10. */
|
|
302
|
+
pngScale?: number;
|
|
303
|
+
/** Share sheet title. Default `label`. */
|
|
304
|
+
shareTitle?: string;
|
|
305
|
+
/** Printed width of the code in millimetres. Default 50. */
|
|
306
|
+
printSizeMm?: number;
|
|
307
|
+
/**
|
|
308
|
+
* Size of the action buttons. Default `"lg"`, which is 44px tall: WCAG
|
|
309
|
+
* 2.5.5's AAA target size. Smaller sizes still meet AA's 24px (2.5.8).
|
|
310
|
+
*/
|
|
311
|
+
buttonSize?: Size;
|
|
312
|
+
/** Button text and announcements, for translation. Partial; the rest default. */
|
|
313
|
+
labels?: Partial<QrCodePanelLabels>;
|
|
314
|
+
/** Called once per action, with how it ended. */
|
|
315
|
+
onAction?: (event: QrCodeActionEvent) => void;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* A QR code with what a person does with one: download it as SVG or PNG,
|
|
320
|
+
* share it (the Web Share sheet, or a copy where there is none), print it, and
|
|
321
|
+
* read the value as text.
|
|
322
|
+
*
|
|
323
|
+
* ## Why a panel, and not props on `<QrCode>`
|
|
324
|
+
*
|
|
325
|
+
* `<QrCode>` is an `<svg>`: it drops into a label template, a PDF, a canvas or
|
|
326
|
+
* a badge and draws a code, nothing else. Buttons, a live region and a print
|
|
327
|
+
* frame inside an `<svg>` would be invalid markup, and making it a `<div>`
|
|
328
|
+
* would break every caller that styles or measures it as an image. So the
|
|
329
|
+
* actions compose AROUND it, the way `Card` composes its sections, and the
|
|
330
|
+
* file formats are separate functions (`qrCodeSvg`, `qrCodePng`) that a host
|
|
331
|
+
* or an agent can call without rendering anything.
|
|
332
|
+
*
|
|
333
|
+
* ## The code tile is light in dark mode too
|
|
334
|
+
*
|
|
335
|
+
* The panel draws black modules on a white tile, quiet zone included, in both
|
|
336
|
+
* colour schemes. A QR code is read by contrast between dark modules and a
|
|
337
|
+
* LIGHT surround; most scanners do not read an inverted code, and the quiet
|
|
338
|
+
* zone must be the light colour for the finder patterns to be found. A dark
|
|
339
|
+
* page around a white tile is fine. Black on white is 21:1, past WCAG AAA.
|
|
340
|
+
*
|
|
341
|
+
* ## Accessibility
|
|
342
|
+
*
|
|
343
|
+
* - The group is named by `label`, and so is the code inside it (`role="img"`).
|
|
344
|
+
* - `showValue` puts the value on screen as selectable text, because a code is
|
|
345
|
+
* unusable to anyone who cannot point a second device at the screen.
|
|
346
|
+
* - Every action is a react-fancy `Button` with a visible text label, in the
|
|
347
|
+
* tab order, operable by Enter and Space, with the kit's `focus-visible`
|
|
348
|
+
* ring. Default size `lg` is 44px tall, WCAG 2.5.5's AAA target size.
|
|
349
|
+
* - What each action did is announced through a polite `role="status"`.
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* ```tsx
|
|
353
|
+
* <QrCodePanel
|
|
354
|
+
* value="https://example.com/r/AbC123"
|
|
355
|
+
* label="Your sign-up link"
|
|
356
|
+
* showValue
|
|
357
|
+
* fileName="sign-up-link"
|
|
358
|
+
* onAction={(event) => console.log(event)}
|
|
359
|
+
* />
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
declare const QrCodePanel: react.ForwardRefExoticComponent<QrCodePanelProps & react.RefAttributes<HTMLDivElement>>;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Files of a QR code: a standalone SVG and a PNG.
|
|
366
|
+
*
|
|
367
|
+
* Both are drawn from {@link modulePath}, the builder `<QrCode>` uses on
|
|
368
|
+
* screen, so a downloaded file carries exactly the modules the person saw.
|
|
369
|
+
*
|
|
370
|
+
* ## A file is always opaque
|
|
371
|
+
*
|
|
372
|
+
* On screen a code can inherit its colours: `currentColor` modules on a
|
|
373
|
+
* `transparent` background take whatever the page puts behind them. A file has
|
|
374
|
+
* no page behind it. A PNG with a transparent background opens dark-on-dark in
|
|
375
|
+
* every image viewer with a dark theme, and dark-on-dark does not scan. So in
|
|
376
|
+
* a file, `transparent` (or no background) becomes white and `currentColor`
|
|
377
|
+
* becomes black. Explicit colours are kept as given: choosing a dark
|
|
378
|
+
* background is the caller's decision, and the docs say what it costs.
|
|
379
|
+
*/
|
|
380
|
+
interface QrCodeFileOptions {
|
|
381
|
+
/**
|
|
382
|
+
* What the code is FOR, e.g. "Your sign-up link". Written into the SVG as
|
|
383
|
+
* its `<title>` and accessible name, so the file still says what it is when
|
|
384
|
+
* it is opened, attached or printed somewhere else. Required, as on
|
|
385
|
+
* `<QrCode>`.
|
|
386
|
+
*/
|
|
387
|
+
label: string;
|
|
388
|
+
errorCorrection?: QrErrorCorrection;
|
|
389
|
+
mode?: QrMode;
|
|
390
|
+
version?: number;
|
|
391
|
+
/** Modules of quiet zone. Default 4, the standard's minimum. */
|
|
392
|
+
quietZone?: number;
|
|
393
|
+
/** Module colour. Default and `currentColor` both mean `#000000`. */
|
|
394
|
+
foreground?: string;
|
|
395
|
+
/** Background colour. Default and `transparent` both mean `#ffffff`. */
|
|
396
|
+
background?: string;
|
|
397
|
+
}
|
|
398
|
+
interface QrCodeSvgOptions extends QrCodeFileOptions {
|
|
399
|
+
/** Width and height in pixels. Default: ten pixels per module. */
|
|
400
|
+
size?: number;
|
|
401
|
+
}
|
|
402
|
+
interface QrCodePngOptions extends QrCodeFileOptions {
|
|
403
|
+
/**
|
|
404
|
+
* Pixels per module, rounded DOWN to a whole number. Default 10.
|
|
405
|
+
*
|
|
406
|
+
* Whole numbers only, because a module drawn across a fraction of a pixel
|
|
407
|
+
* gets a blurred edge, and a scanner reading a blurred edge guesses. Clamped
|
|
408
|
+
* to at least 1, and down so the image is at most 8192 pixels a side.
|
|
409
|
+
*/
|
|
410
|
+
scale?: number;
|
|
411
|
+
/**
|
|
412
|
+
* The canvas to draw on. Default: a new `<canvas>`. Pass one to draw where
|
|
413
|
+
* there is no `document` (an `OffscreenCanvas` will not do: it has no
|
|
414
|
+
* `toBlob`) or to inspect the drawing in a test.
|
|
415
|
+
*/
|
|
416
|
+
canvas?: HTMLCanvasElement;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* A QR code as a standalone SVG document, with an XML declaration, a
|
|
420
|
+
* `<title>`, an accessible name and an opaque background.
|
|
421
|
+
*
|
|
422
|
+
* @throws RangeError when the value cannot fit, exactly as `encodeQr` does,
|
|
423
|
+
* and as cheaply: an impossible value is refused from its length alone.
|
|
424
|
+
*/
|
|
425
|
+
declare function qrCodeSvg(value: string, options: QrCodeSvgOptions): string;
|
|
426
|
+
/**
|
|
427
|
+
* A QR code as a PNG, drawn on a canvas from the same path data as the SVG.
|
|
428
|
+
*
|
|
429
|
+
* It does not load the SVG into an `<img>` first. That route needs a `blob:`
|
|
430
|
+
* or `data:` image, which a Content Security Policy of `img-src 'self'`
|
|
431
|
+
* blocks, and the download would then fail on exactly the sites careful
|
|
432
|
+
* enough to set one. `Path2D` takes the SVG path string directly, so the
|
|
433
|
+
* geometry is the SVG's and nothing is fetched.
|
|
434
|
+
*
|
|
435
|
+
* The background is painted over the whole canvas, quiet zone included, before
|
|
436
|
+
* any module. Each colour is set over a known default first: a canvas ignores
|
|
437
|
+
* a colour it cannot parse and keeps the previous one, so an unreadable
|
|
438
|
+
* background would otherwise inherit black and produce a black square.
|
|
439
|
+
*/
|
|
440
|
+
declare function qrCodePng(value: string, options: QrCodePngOptions): Promise<Blob>;
|
|
441
|
+
|
|
442
|
+
export { type EncodeOptions, QrCode, type QrCodeAction, type QrCodeActionEvent, type QrCodeActionOutcome, type QrCodeFileOptions, QrCodePanel, type QrCodePanelLabels, type QrCodePanelProps, type QrCodePngOptions, type QrCodeProps, type QrCodeSvgOptions, type QrErrorCorrection, type QrMode, type QrSymbol, encodeQr, qrCodePng, qrCodeSvg, selectMode };
|
package/dist/qr-code.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { SVGAttributes } from 'react';
|
|
2
|
+
import { SVGAttributes, HTMLAttributes } from 'react';
|
|
3
|
+
import { S as Size } from './types-DJI492iY.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* ISO/IEC 18004 table data for the QR encoder. **Data, not logic** — kept in
|
|
@@ -220,4 +221,222 @@ interface QrCodeProps extends Omit<SVGAttributes<SVGSVGElement>, "children" | "v
|
|
|
220
221
|
*/
|
|
221
222
|
declare const QrCode: react.ForwardRefExoticComponent<QrCodeProps & react.RefAttributes<SVGSVGElement>>;
|
|
222
223
|
|
|
223
|
-
|
|
224
|
+
/** What a person can do with a code. Each renders one `Button`. */
|
|
225
|
+
type QrCodeAction = "download-svg" | "download-png" | "share" | "print";
|
|
226
|
+
/**
|
|
227
|
+
* How an action ended.
|
|
228
|
+
*
|
|
229
|
+
* - `done`: the file was handed to the browser, the share sheet completed, the
|
|
230
|
+
* value was copied, or the print dialog was opened.
|
|
231
|
+
* - `cancelled`: the person dismissed the share sheet. Not an error.
|
|
232
|
+
* - `failed`: nothing happened that the person asked for; `error` says why.
|
|
233
|
+
*/
|
|
234
|
+
type QrCodeActionOutcome = "done" | "cancelled" | "failed";
|
|
235
|
+
/** One action, reported. Plain JSON, so it can go straight to an agent or a log. */
|
|
236
|
+
interface QrCodeActionEvent {
|
|
237
|
+
action: QrCodeAction;
|
|
238
|
+
outcome: QrCodeActionOutcome;
|
|
239
|
+
/** For `share`: whether the Web Share sheet or the clipboard carried it. */
|
|
240
|
+
via?: "share" | "clipboard";
|
|
241
|
+
/** For a download: the file name the browser was given. */
|
|
242
|
+
fileName?: string;
|
|
243
|
+
/** For `failed`: the reason, as text. */
|
|
244
|
+
error?: string;
|
|
245
|
+
}
|
|
246
|
+
/** Visible button text and the announcements read out after each action. */
|
|
247
|
+
interface QrCodePanelLabels {
|
|
248
|
+
downloadSvg: string;
|
|
249
|
+
downloadPng: string;
|
|
250
|
+
share: string;
|
|
251
|
+
/** The share button's text where Web Share is absent and a web link is copied. */
|
|
252
|
+
copyLink: string;
|
|
253
|
+
/** The same, for a value that is not a web link. */
|
|
254
|
+
copy: string;
|
|
255
|
+
print: string;
|
|
256
|
+
downloaded: string;
|
|
257
|
+
shared: string;
|
|
258
|
+
copied: string;
|
|
259
|
+
printing: string;
|
|
260
|
+
failed: string;
|
|
261
|
+
}
|
|
262
|
+
interface QrCodePanelProps extends Omit<HTMLAttributes<HTMLDivElement>, "children" | "onChange"> {
|
|
263
|
+
/** What the code carries. Any string; see `QrCode`'s `value`. */
|
|
264
|
+
value: string;
|
|
265
|
+
/**
|
|
266
|
+
* What the code is FOR, e.g. "Your sign-up link". Required. Names the code,
|
|
267
|
+
* the group around it, the SVG file's `<title>`, the print page's title,
|
|
268
|
+
* and the share sheet's title unless `shareTitle` is set.
|
|
269
|
+
*/
|
|
270
|
+
label: string;
|
|
271
|
+
/** Rendered size of the code in pixels. Default 192. */
|
|
272
|
+
size?: number;
|
|
273
|
+
errorCorrection?: QrErrorCorrection;
|
|
274
|
+
quietZone?: number;
|
|
275
|
+
/**
|
|
276
|
+
* Module colour. Default `#000000`, on screen as well as in files.
|
|
277
|
+
*
|
|
278
|
+
* The panel does NOT inherit text colour the way a bare `<QrCode>` does: a
|
|
279
|
+
* code must be dark on light to scan, so the panel pins black on white in
|
|
280
|
+
* dark mode too. Black on white is 21:1, past WCAG AAA's 7:1.
|
|
281
|
+
*/
|
|
282
|
+
foreground?: string;
|
|
283
|
+
/** Background, quiet zone included. Default `#ffffff`, in both colour schemes. */
|
|
284
|
+
background?: string;
|
|
285
|
+
mode?: QrMode;
|
|
286
|
+
version?: number;
|
|
287
|
+
/**
|
|
288
|
+
* Which actions to offer, in order. Default all four:
|
|
289
|
+
* `["download-svg", "download-png", "share", "print"]`. `[]` renders none.
|
|
290
|
+
*/
|
|
291
|
+
actions?: readonly QrCodeAction[];
|
|
292
|
+
/**
|
|
293
|
+
* Show the value as selectable text under the code, and on the printed page.
|
|
294
|
+
* Default `false`, because not every value is meant to be read out: a WiFi
|
|
295
|
+
* block carries a password. Turn it on for a link or a reference a person
|
|
296
|
+
* might type instead of scanning.
|
|
297
|
+
*/
|
|
298
|
+
showValue?: boolean;
|
|
299
|
+
/** Download file name, without extension. Sanitised. Default `"qr-code"`. */
|
|
300
|
+
fileName?: string;
|
|
301
|
+
/** PNG pixels per module, a whole number. Default 10. */
|
|
302
|
+
pngScale?: number;
|
|
303
|
+
/** Share sheet title. Default `label`. */
|
|
304
|
+
shareTitle?: string;
|
|
305
|
+
/** Printed width of the code in millimetres. Default 50. */
|
|
306
|
+
printSizeMm?: number;
|
|
307
|
+
/**
|
|
308
|
+
* Size of the action buttons. Default `"lg"`, which is 44px tall: WCAG
|
|
309
|
+
* 2.5.5's AAA target size. Smaller sizes still meet AA's 24px (2.5.8).
|
|
310
|
+
*/
|
|
311
|
+
buttonSize?: Size;
|
|
312
|
+
/** Button text and announcements, for translation. Partial; the rest default. */
|
|
313
|
+
labels?: Partial<QrCodePanelLabels>;
|
|
314
|
+
/** Called once per action, with how it ended. */
|
|
315
|
+
onAction?: (event: QrCodeActionEvent) => void;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* A QR code with what a person does with one: download it as SVG or PNG,
|
|
320
|
+
* share it (the Web Share sheet, or a copy where there is none), print it, and
|
|
321
|
+
* read the value as text.
|
|
322
|
+
*
|
|
323
|
+
* ## Why a panel, and not props on `<QrCode>`
|
|
324
|
+
*
|
|
325
|
+
* `<QrCode>` is an `<svg>`: it drops into a label template, a PDF, a canvas or
|
|
326
|
+
* a badge and draws a code, nothing else. Buttons, a live region and a print
|
|
327
|
+
* frame inside an `<svg>` would be invalid markup, and making it a `<div>`
|
|
328
|
+
* would break every caller that styles or measures it as an image. So the
|
|
329
|
+
* actions compose AROUND it, the way `Card` composes its sections, and the
|
|
330
|
+
* file formats are separate functions (`qrCodeSvg`, `qrCodePng`) that a host
|
|
331
|
+
* or an agent can call without rendering anything.
|
|
332
|
+
*
|
|
333
|
+
* ## The code tile is light in dark mode too
|
|
334
|
+
*
|
|
335
|
+
* The panel draws black modules on a white tile, quiet zone included, in both
|
|
336
|
+
* colour schemes. A QR code is read by contrast between dark modules and a
|
|
337
|
+
* LIGHT surround; most scanners do not read an inverted code, and the quiet
|
|
338
|
+
* zone must be the light colour for the finder patterns to be found. A dark
|
|
339
|
+
* page around a white tile is fine. Black on white is 21:1, past WCAG AAA.
|
|
340
|
+
*
|
|
341
|
+
* ## Accessibility
|
|
342
|
+
*
|
|
343
|
+
* - The group is named by `label`, and so is the code inside it (`role="img"`).
|
|
344
|
+
* - `showValue` puts the value on screen as selectable text, because a code is
|
|
345
|
+
* unusable to anyone who cannot point a second device at the screen.
|
|
346
|
+
* - Every action is a react-fancy `Button` with a visible text label, in the
|
|
347
|
+
* tab order, operable by Enter and Space, with the kit's `focus-visible`
|
|
348
|
+
* ring. Default size `lg` is 44px tall, WCAG 2.5.5's AAA target size.
|
|
349
|
+
* - What each action did is announced through a polite `role="status"`.
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* ```tsx
|
|
353
|
+
* <QrCodePanel
|
|
354
|
+
* value="https://example.com/r/AbC123"
|
|
355
|
+
* label="Your sign-up link"
|
|
356
|
+
* showValue
|
|
357
|
+
* fileName="sign-up-link"
|
|
358
|
+
* onAction={(event) => console.log(event)}
|
|
359
|
+
* />
|
|
360
|
+
* ```
|
|
361
|
+
*/
|
|
362
|
+
declare const QrCodePanel: react.ForwardRefExoticComponent<QrCodePanelProps & react.RefAttributes<HTMLDivElement>>;
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Files of a QR code: a standalone SVG and a PNG.
|
|
366
|
+
*
|
|
367
|
+
* Both are drawn from {@link modulePath}, the builder `<QrCode>` uses on
|
|
368
|
+
* screen, so a downloaded file carries exactly the modules the person saw.
|
|
369
|
+
*
|
|
370
|
+
* ## A file is always opaque
|
|
371
|
+
*
|
|
372
|
+
* On screen a code can inherit its colours: `currentColor` modules on a
|
|
373
|
+
* `transparent` background take whatever the page puts behind them. A file has
|
|
374
|
+
* no page behind it. A PNG with a transparent background opens dark-on-dark in
|
|
375
|
+
* every image viewer with a dark theme, and dark-on-dark does not scan. So in
|
|
376
|
+
* a file, `transparent` (or no background) becomes white and `currentColor`
|
|
377
|
+
* becomes black. Explicit colours are kept as given: choosing a dark
|
|
378
|
+
* background is the caller's decision, and the docs say what it costs.
|
|
379
|
+
*/
|
|
380
|
+
interface QrCodeFileOptions {
|
|
381
|
+
/**
|
|
382
|
+
* What the code is FOR, e.g. "Your sign-up link". Written into the SVG as
|
|
383
|
+
* its `<title>` and accessible name, so the file still says what it is when
|
|
384
|
+
* it is opened, attached or printed somewhere else. Required, as on
|
|
385
|
+
* `<QrCode>`.
|
|
386
|
+
*/
|
|
387
|
+
label: string;
|
|
388
|
+
errorCorrection?: QrErrorCorrection;
|
|
389
|
+
mode?: QrMode;
|
|
390
|
+
version?: number;
|
|
391
|
+
/** Modules of quiet zone. Default 4, the standard's minimum. */
|
|
392
|
+
quietZone?: number;
|
|
393
|
+
/** Module colour. Default and `currentColor` both mean `#000000`. */
|
|
394
|
+
foreground?: string;
|
|
395
|
+
/** Background colour. Default and `transparent` both mean `#ffffff`. */
|
|
396
|
+
background?: string;
|
|
397
|
+
}
|
|
398
|
+
interface QrCodeSvgOptions extends QrCodeFileOptions {
|
|
399
|
+
/** Width and height in pixels. Default: ten pixels per module. */
|
|
400
|
+
size?: number;
|
|
401
|
+
}
|
|
402
|
+
interface QrCodePngOptions extends QrCodeFileOptions {
|
|
403
|
+
/**
|
|
404
|
+
* Pixels per module, rounded DOWN to a whole number. Default 10.
|
|
405
|
+
*
|
|
406
|
+
* Whole numbers only, because a module drawn across a fraction of a pixel
|
|
407
|
+
* gets a blurred edge, and a scanner reading a blurred edge guesses. Clamped
|
|
408
|
+
* to at least 1, and down so the image is at most 8192 pixels a side.
|
|
409
|
+
*/
|
|
410
|
+
scale?: number;
|
|
411
|
+
/**
|
|
412
|
+
* The canvas to draw on. Default: a new `<canvas>`. Pass one to draw where
|
|
413
|
+
* there is no `document` (an `OffscreenCanvas` will not do: it has no
|
|
414
|
+
* `toBlob`) or to inspect the drawing in a test.
|
|
415
|
+
*/
|
|
416
|
+
canvas?: HTMLCanvasElement;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* A QR code as a standalone SVG document, with an XML declaration, a
|
|
420
|
+
* `<title>`, an accessible name and an opaque background.
|
|
421
|
+
*
|
|
422
|
+
* @throws RangeError when the value cannot fit, exactly as `encodeQr` does,
|
|
423
|
+
* and as cheaply: an impossible value is refused from its length alone.
|
|
424
|
+
*/
|
|
425
|
+
declare function qrCodeSvg(value: string, options: QrCodeSvgOptions): string;
|
|
426
|
+
/**
|
|
427
|
+
* A QR code as a PNG, drawn on a canvas from the same path data as the SVG.
|
|
428
|
+
*
|
|
429
|
+
* It does not load the SVG into an `<img>` first. That route needs a `blob:`
|
|
430
|
+
* or `data:` image, which a Content Security Policy of `img-src 'self'`
|
|
431
|
+
* blocks, and the download would then fail on exactly the sites careful
|
|
432
|
+
* enough to set one. `Path2D` takes the SVG path string directly, so the
|
|
433
|
+
* geometry is the SVG's and nothing is fetched.
|
|
434
|
+
*
|
|
435
|
+
* The background is painted over the whole canvas, quiet zone included, before
|
|
436
|
+
* any module. Each colour is set over a known default first: a canvas ignores
|
|
437
|
+
* a colour it cannot parse and keeps the previous one, so an unreadable
|
|
438
|
+
* background would otherwise inherit black and produce a black square.
|
|
439
|
+
*/
|
|
440
|
+
declare function qrCodePng(value: string, options: QrCodePngOptions): Promise<Blob>;
|
|
441
|
+
|
|
442
|
+
export { type EncodeOptions, QrCode, type QrCodeAction, type QrCodeActionEvent, type QrCodeActionOutcome, type QrCodeFileOptions, QrCodePanel, type QrCodePanelLabels, type QrCodePanelProps, type QrCodePngOptions, type QrCodeProps, type QrCodeSvgOptions, type QrErrorCorrection, type QrMode, type QrSymbol, encodeQr, qrCodePng, qrCodeSvg, selectMode };
|
package/dist/qr-code.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export { QrCode, encodeQr, selectMode } from './chunk-
|
|
1
|
+
export { QrCode, QrCodePanel, encodeQr, qrCodePng, qrCodeSvg, selectMode } from './chunk-PIG3UTHU.js';
|
|
2
|
+
import './chunk-4GPH7HOR.js';
|
|
3
|
+
import './chunk-45BBNJQD.js';
|
|
4
|
+
import './chunk-J3A4Z2P7.js';
|
|
2
5
|
import './chunk-MMW2JGKZ.js';
|
|
3
6
|
//# sourceMappingURL=qr-code.js.map
|
|
4
7
|
//# sourceMappingURL=qr-code.js.map
|
package/docs/PromptInput.md
CHANGED
|
@@ -31,8 +31,12 @@ import { PromptInput } from "@particle-academy/react-fancy";
|
|
|
31
31
|
## Features
|
|
32
32
|
|
|
33
33
|
- Auto-resizes up to `maxHeight`.
|
|
34
|
-
- `/` opens a filtered command palette. ↑/↓ navigate, Enter inserts.
|
|
34
|
+
- `/` opens a filtered command palette. ↑/↓ navigate, Enter inserts. The
|
|
35
|
+
highlighted row is kept scrolled into view.
|
|
35
36
|
- `@` opens a mention picker filtered against `mentions`.
|
|
37
|
+
- Long command names and hints wrap inside the menu; a long mention name is
|
|
38
|
+
truncated with an ellipsis and kept whole in its `title`. The menu never
|
|
39
|
+
scrolls sideways.
|
|
36
40
|
- Drop files anywhere on the input to attach. Chip bar shows attachments.
|
|
37
41
|
- ⌘+Enter (or Ctrl+Enter) submits. Plain Enter inserts a newline. An Enter
|
|
38
42
|
that confirms an IME composition neither submits nor picks from a menu.
|
|
@@ -225,7 +229,11 @@ Data handles: the root `[data-react-fancy-prompt-input]` (with
|
|
|
225
229
|
`[data-react-fancy-prompt-input-attachment="<id>"]`, plus `-attach`, `-send`,
|
|
226
230
|
`-meter`, `-hint` and `-error`. The text field is
|
|
227
231
|
`[data-react-fancy-prompt-input-textarea]`, or `[data-react-fancy-composer-input]`
|
|
228
|
-
with inline pills on; `inputId` gives it one id in both modes.
|
|
232
|
+
with inline pills on; `inputId` gives it one id in both modes. The open `/` or
|
|
233
|
+
`@` menu is `[data-react-fancy-prompt-input-menu="cmd" | "mention"]`, a
|
|
234
|
+
`role="listbox"`; each row is a `role="option"`
|
|
235
|
+
`[data-react-fancy-prompt-input-menu-item="<command name or mention id>"]`, and
|
|
236
|
+
the highlighted one has `aria-selected="true"`.
|
|
229
237
|
|
|
230
238
|
## Defaults
|
|
231
239
|
|
package/docs/QrCode.md
CHANGED
|
@@ -164,6 +164,114 @@ value accurately.
|
|
|
164
164
|
Capacity at the largest symbol (version 40, level `L`): **7,089** digits,
|
|
165
165
|
**4,296** alphanumeric characters, or **2,953** bytes.
|
|
166
166
|
|
|
167
|
+
## `QrCodePanel`: download, share, print
|
|
168
|
+
|
|
169
|
+
`<QrCode>` is only an `<svg>`. `QrCodePanel` composes it with what a person does
|
|
170
|
+
with a code: download it as SVG or PNG, share it, print it, and read the value
|
|
171
|
+
as text.
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
import { QrCodePanel } from "@particle-academy/react-fancy";
|
|
175
|
+
|
|
176
|
+
<QrCodePanel
|
|
177
|
+
value="https://example.com/r/AbC123"
|
|
178
|
+
label="Your sign-up link"
|
|
179
|
+
showValue
|
|
180
|
+
fileName="sign-up-link"
|
|
181
|
+
onAction={(event) => console.log(event)}
|
|
182
|
+
/>
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
It is a composition rather than props on `<QrCode>` because buttons, a live
|
|
186
|
+
region and a print frame cannot live inside an `<svg>`, and turning `<QrCode>`
|
|
187
|
+
into a `<div>` would break every caller that places it as an image.
|
|
188
|
+
|
|
189
|
+
| Prop | Type | Default | Description |
|
|
190
|
+
|------|------|---------|-------------|
|
|
191
|
+
| value, label, size, errorCorrection, quietZone, mode, version | | | As on `<QrCode>`. `label` also names the group, the SVG file's `<title>`, the print page and the share sheet. |
|
|
192
|
+
| foreground | `string` | `"#000000"` | Module colour, on screen and in files. |
|
|
193
|
+
| background | `string` | `"#ffffff"` | Background and quiet zone, in **both** colour schemes. |
|
|
194
|
+
| actions | `QrCodeAction[]` | all four | Any of `"download-svg"`, `"download-png"`, `"share"`, `"print"`, in the order given. `[]` renders none. |
|
|
195
|
+
| showValue | `boolean` | `false` | Show the value as selectable text, and on the printed page. |
|
|
196
|
+
| fileName | `string` | `"qr-code"` | Download name without extension. Letters, digits, `.`, `_`, `-` are kept; any other run becomes `-`. |
|
|
197
|
+
| pngScale | `number` | `10` | PNG pixels per module, rounded down to a whole number. |
|
|
198
|
+
| shareTitle | `string` | `label` | Title for the share sheet. |
|
|
199
|
+
| printSizeMm | `number` | `50` | Printed width of the code. |
|
|
200
|
+
| buttonSize | `Size` | `"lg"` | `lg` is 44px tall, WCAG 2.5.5's AAA target size. |
|
|
201
|
+
| labels | `Partial<QrCodePanelLabels>` | English | Button text and announcements, for translation. |
|
|
202
|
+
| onAction | `(event: QrCodeActionEvent) => void` | | Called once per action. |
|
|
203
|
+
|
|
204
|
+
`onAction` receives plain JSON: `{ action, outcome, via?, fileName?, error? }`,
|
|
205
|
+
where `outcome` is `"done"`, `"cancelled"` (the person dismissed the share sheet)
|
|
206
|
+
or `"failed"` (with `error`). Every action reports, including a failure, so
|
|
207
|
+
nothing fails silently.
|
|
208
|
+
|
|
209
|
+
### Each action
|
|
210
|
+
|
|
211
|
+
- **Download SVG**: a standalone SVG file with an XML declaration, a `<title>`
|
|
212
|
+
and an accessible name. Its path is the on-screen path, byte for byte.
|
|
213
|
+
- **Download PNG**: drawn on a canvas from the same path data, at a whole number
|
|
214
|
+
of pixels per module, so no module edge is blurred. It is drawn with `Path2D`
|
|
215
|
+
rather than by loading the SVG into an `<img>`, because a Content Security
|
|
216
|
+
Policy of `img-src 'self'` blocks the `blob:` or `data:` image that route needs.
|
|
217
|
+
At most 8192 pixels a side.
|
|
218
|
+
- **Share**: the Web Share sheet where the browser has one, sharing a web link
|
|
219
|
+
as `url` and anything else as `text`. Where it is absent, or `canShare`
|
|
220
|
+
refuses the data, the button reads "Copy link" (or "Copy" for a value that is
|
|
221
|
+
not a web link) and copies the value instead. A dismissed share sheet is
|
|
222
|
+
`cancelled`, not an error.
|
|
223
|
+
- **Print**: a hidden frame holding nothing but the code, at `printSizeMm`, and
|
|
224
|
+
the value when `showValue` is on, then the browser's print dialog. The page is
|
|
225
|
+
built with DOM calls, never written as HTML, so neither `label` nor `value` is
|
|
226
|
+
parsed as markup. Styling goes through the CSSOM, which a CSP without
|
|
227
|
+
`'unsafe-inline'` allows.
|
|
228
|
+
|
|
229
|
+
### The code tile is light in dark mode too
|
|
230
|
+
|
|
231
|
+
A QR code is read by the contrast between dark modules and a **light**
|
|
232
|
+
surround, quiet zone included: most scanners do not read an inverted code. So
|
|
233
|
+
the panel draws black on white in both colour schemes. Black on white is 21:1,
|
|
234
|
+
past WCAG AAA's 7:1. A dark page around a white tile is fine. If you pass your
|
|
235
|
+
own colours, keep the background the lighter one.
|
|
236
|
+
|
|
237
|
+
**Files are always opaque.** In a downloaded SVG or PNG, `transparent` (or no
|
|
238
|
+
background) becomes white and `currentColor` becomes black, because a file has
|
|
239
|
+
no page behind it to inherit. Explicit colours are kept as given.
|
|
240
|
+
|
|
241
|
+
### Accessibility
|
|
242
|
+
|
|
243
|
+
- The group and the code are both named by `label`.
|
|
244
|
+
- `showValue` puts the value on screen as selectable text, for anyone who cannot
|
|
245
|
+
point a second device at the screen. It is off by default because not every
|
|
246
|
+
value is for reading out: a WiFi block carries a password.
|
|
247
|
+
- Every action is a react-fancy `Button` with visible text, in the tab order,
|
|
248
|
+
operable by Enter and Space, with the kit's `focus-visible` ring.
|
|
249
|
+
- What each action did is announced through a polite `role="status"` region.
|
|
250
|
+
|
|
251
|
+
### Stable handles
|
|
252
|
+
|
|
253
|
+
`[data-react-fancy-qr-code-panel]` on the root, `-panel-code`, `-panel-value`,
|
|
254
|
+
`-panel-actions` and `-panel-status` on its parts, and
|
|
255
|
+
`[data-react-fancy-qr-code-action="download-png"]` (and so on) on each button.
|
|
256
|
+
The share button also carries `data-via="share"` or `data-via="clipboard"`.
|
|
257
|
+
|
|
258
|
+
## The files on their own
|
|
259
|
+
|
|
260
|
+
The panel's file formats are plain functions, for a host or an agent that wants
|
|
261
|
+
a file without rendering anything:
|
|
262
|
+
|
|
263
|
+
```tsx
|
|
264
|
+
import { qrCodePng, qrCodeSvg } from "@particle-academy/react-fancy";
|
|
265
|
+
|
|
266
|
+
const svg: string = qrCodeSvg("https://example.com/r/AbC123", { label: "Your sign-up link" });
|
|
267
|
+
const png: Blob = await qrCodePng("https://example.com/r/AbC123", { label: "Your sign-up link", scale: 12 });
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
`qrCodeSvg` works anywhere, including on the server. `qrCodePng` needs a
|
|
271
|
+
browser canvas. Both take `errorCorrection`, `mode`, `version`, `quietZone`,
|
|
272
|
+
`foreground` and `background`, and throw the encoder's `RangeError` for a value
|
|
273
|
+
that cannot fit.
|
|
274
|
+
|
|
167
275
|
## Not supported
|
|
168
276
|
|
|
169
277
|
Kanji mode and structured append. Neither has a caller here, and an untested
|