@webx-ui/module-catalog 0.2.0 → 0.4.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/dist/module.d.ts CHANGED
@@ -16,7 +16,8 @@ export interface CatalogOptions {
16
16
  * group, beside the satellites (brands, stock, labels). «Deleted» is reached from the head of the
17
17
  * products: it holds categories too, but it is visited rarely, and by whoever may delete.
18
18
  *
19
- * The three node types are what only this module can draw on its two screens: a category picker
20
- * that knows the tree, the «Filters» tab of a category (§6.2), and the gallery.
19
+ * The node types are what only this module can draw: a category picker that knows the tree, the
20
+ * «Filters» tab of a category (§6.2), the gallery, and the tone of a reference book's record —
21
+ * the satellites' screens use it, and the six tones are the core's (`Dictionary`).
21
22
  */
22
23
  export declare function catalog(options?: CatalogOptions): AdminModule[];
package/dist/style.css CHANGED
@@ -1 +1 @@
1
- .wx-catalog-categories[data-v-5385c84c]{min-width:0}.wx-catalog-categories__name[data-v-5385c84c]{font-weight:var(--wx-font-weight-medium)}.wx-catalog-categories__name.is-hidden[data-v-5385c84c]{color:var(--wx-text-muted)}.wx-catalog-categories__count[data-v-5385c84c]{color:var(--wx-color-primary);font-variant-numeric:tabular-nums;text-decoration:none}.wx-catalog-categories__count[data-v-5385c84c]:hover{text-decoration:underline}.wx-catalog-category-editor[data-v-45d5817b]{display:flex;flex-direction:column;gap:var(--wx-gap, var(--wx-space-16));container-type:inline-size}.wx-catalog-category-editor__ghost[data-v-45d5817b]{max-width:420px}.wx-catalog-deleted[data-v-1fad643b]{min-width:0}.wx-catalog-deleted__name[data-v-1fad643b]{display:flex;flex-direction:column;min-width:0}.wx-catalog-deleted__title[data-v-1fad643b]{font-weight:var(--wx-font-weight-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wx-catalog-deleted__code[data-v-1fad643b]{font-family:var(--wx-font-family-mono);font-size:var(--wx-font-size-sm);color:var(--wx-text-muted)}.wx-catalog-deleted__ref[data-v-1fad643b]{display:flex;flex-wrap:wrap;align-items:center;gap:var(--wx-space-4) var(--wx-space-8);min-width:0}.wx-catalog-facets[data-v-4ca00a4d]{display:flex;flex-direction:column;gap:var(--wx-space-12)}.wx-catalog-facets__own[data-v-4ca00a4d],.wx-catalog-facets__inherited[data-v-4ca00a4d]{display:flex;flex-direction:column;gap:var(--wx-space-4)}.wx-catalog-facets[data-v-4ca00a4d] .wx-sortable-list__content{display:flex;align-items:center;gap:var(--wx-space-8);min-width:0}.wx-catalog-facets__name[data-v-4ca00a4d]{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wx-catalog-facets__name.is-off[data-v-4ca00a4d]{color:var(--wx-text-muted)}.wx-catalog-gallery[data-v-695c0f5d]{display:flex;flex-direction:column;gap:var(--wx-space-16);container-type:inline-size}.wx-catalog-gallery[data-v-695c0f5d] .wx-sortable-list__content{min-width:0}.wx-catalog-gallery__item[data-v-695c0f5d]{display:grid;grid-template-columns:72px minmax(0,1fr);gap:var(--wx-space-12);align-items:center}.wx-catalog-gallery__thumb[data-v-695c0f5d]{position:relative;display:block;width:72px;aspect-ratio:1;overflow:clip;border-radius:var(--wx-radius-sm);background:var(--wx-bg-subtle);border:1px solid var(--wx-border-default)}.wx-catalog-gallery__thumb img[data-v-695c0f5d]{width:100%;height:100%;min-width:0;object-fit:contain;display:block}.wx-catalog-gallery__main[data-v-695c0f5d]{position:absolute;inset-inline-start:var(--wx-space-2);inset-block-start:var(--wx-space-2)}.wx-catalog-gallery__size[data-v-695c0f5d]{position:absolute;inset-inline:0;inset-block-end:0;padding-block:var(--wx-space-2);background:var(--wx-bg-overlay);color:var(--wx-color-white);font-size:var(--wx-font-size-xs);line-height:1.2;text-align:center;white-space:nowrap;font-variant-numeric:tabular-nums}.wx-catalog-gallery__words[data-v-695c0f5d]{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--wx-space-8)}@container (min-width: 640px){.wx-catalog-gallery__words[data-v-695c0f5d]{grid-template-columns:repeat(2,minmax(0,1fr))}}@container (max-width: 420px){.wx-catalog-gallery__item[data-v-695c0f5d]{grid-template-columns:minmax(0,1fr)}}.wx-catalog-gallery__address[data-v-695c0f5d]{display:flex;gap:var(--wx-space-8);align-items:center;max-width:560px}.wx-catalog-gallery__address[data-v-695c0f5d]>:first-child{flex:1;min-width:0}.wx-catalog-product[data-v-837dd378]{display:flex;flex-direction:column;gap:var(--wx-gap, var(--wx-space-16));container-type:inline-size}.wx-catalog-product__ghost[data-v-837dd378]{max-width:420px}.wx-catalog-bulk-params__field[data-v-b83c3fb0]{margin-top:var(--wx-space-16)}.wx-catalog-bulk[data-v-94557c14]{display:contents}.wx-catalog-bulk__progress[data-v-94557c14]{display:grid;gap:var(--wx-space-4);flex:1 1 240px;min-width:0}.wx-catalog-bulk__refused[data-v-94557c14]{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--wx-space-8);flex-basis:100%;min-width:0}.wx-catalog-bulk__errors[data-v-94557c14]{flex-basis:100%;font-size:var(--wx-font-size-sm)}.wx-catalog-bulk__errors summary[data-v-94557c14]{cursor:pointer;color:var(--wx-text-muted)}.wx-catalog-bulk__errors ul[data-v-94557c14]{margin:var(--wx-space-8) 0 0;padding-inline-start:var(--wx-space-18);max-height:200px;overflow:auto}.wx-catalog-products[data-v-44965ffc]{min-width:0}.wx-catalog-products__selection[data-v-44965ffc]{display:flex;flex-wrap:wrap;align-items:center;gap:var(--wx-space-12);padding:var(--wx-space-8) var(--wx-space-16);border-bottom:1px solid var(--wx-border-default);background:var(--wx-bg-subtle)}.wx-catalog-products__image[data-v-44965ffc]{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--wx-radius-sm);overflow:clip;background:var(--wx-bg-subtle);color:var(--wx-text-muted);vertical-align:middle}.wx-catalog-products__image img[data-v-44965ffc]{width:100%;height:100%;min-width:0;object-fit:cover}.wx-catalog-products__name[data-v-44965ffc]{display:flex;flex-direction:column;min-width:0}.wx-catalog-products__title[data-v-44965ffc]{font-weight:var(--wx-font-weight-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wx-catalog-products__sku[data-v-44965ffc]{font-family:var(--wx-font-family-mono);font-size:var(--wx-font-size-sm);color:var(--wx-text-muted);min-height:1em}.wx-catalog-products__price[data-v-44965ffc]{display:inline-flex;flex-direction:column;align-items:flex-end;font-variant-numeric:tabular-nums}.wx-catalog-products__price[data-v-44965ffc]>*{white-space:nowrap}.wx-catalog-products__price small[data-v-44965ffc],.wx-catalog-products__price s[data-v-44965ffc]{font-size:var(--wx-font-size-sm);color:var(--wx-text-muted)}.wx-catalog-products__range[data-v-44965ffc]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--wx-space-8)}
1
+ .wx-catalog-categories[data-v-5385c84c]{min-width:0}.wx-catalog-categories__name[data-v-5385c84c]{font-weight:var(--wx-font-weight-medium)}.wx-catalog-categories__name.is-hidden[data-v-5385c84c]{color:var(--wx-text-muted)}.wx-catalog-categories__count[data-v-5385c84c]{color:var(--wx-color-primary);font-variant-numeric:tabular-nums;text-decoration:none}.wx-catalog-categories__count[data-v-5385c84c]:hover{text-decoration:underline}.wx-catalog-category-editor[data-v-45d5817b]{display:flex;flex-direction:column;gap:var(--wx-gap, var(--wx-space-16));container-type:inline-size}.wx-catalog-category-editor__ghost[data-v-45d5817b]{max-width:420px}.wx-catalog-deleted[data-v-1fad643b]{min-width:0}.wx-catalog-deleted__name[data-v-1fad643b]{display:flex;flex-direction:column;min-width:0}.wx-catalog-deleted__title[data-v-1fad643b]{font-weight:var(--wx-font-weight-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wx-catalog-deleted__code[data-v-1fad643b]{font-family:var(--wx-font-family-mono);font-size:var(--wx-font-size-sm);color:var(--wx-text-muted)}.wx-catalog-deleted__ref[data-v-1fad643b]{display:flex;flex-wrap:wrap;align-items:center;gap:var(--wx-space-4) var(--wx-space-8);min-width:0}.wx-catalog-facets[data-v-4ca00a4d]{display:flex;flex-direction:column;gap:var(--wx-space-12)}.wx-catalog-facets__own[data-v-4ca00a4d],.wx-catalog-facets__inherited[data-v-4ca00a4d]{display:flex;flex-direction:column;gap:var(--wx-space-4)}.wx-catalog-facets[data-v-4ca00a4d] .wx-sortable-list__content{display:flex;align-items:center;gap:var(--wx-space-8);min-width:0}.wx-catalog-facets__name[data-v-4ca00a4d]{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wx-catalog-facets__name.is-off[data-v-4ca00a4d]{color:var(--wx-text-muted)}.wx-catalog-video-progress[data-v-09fd14bf]{display:flex;flex-direction:column;gap:var(--wx-space-4);min-width:0}.wx-catalog-video-progress__line[data-v-09fd14bf]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--wx-space-4) var(--wx-space-8);min-width:0}.wx-catalog-video-progress__figures[data-v-09fd14bf]{font-variant-numeric:tabular-nums;min-width:0}.wx-catalog-video-progress__figure[data-v-09fd14bf]{white-space:nowrap}.wx-catalog-video-progress__buttons[data-v-09fd14bf]{display:flex;gap:var(--wx-space-4);margin-inline-start:auto}.wx-catalog-video-progress.is-failed[data-v-09fd14bf]{flex-direction:row;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--wx-space-4) var(--wx-space-8)}.wx-catalog-gallery[data-v-fdb59e51]{display:flex;flex-direction:column;gap:var(--wx-space-16);container-type:inline-size}.wx-catalog-gallery[data-v-fdb59e51] .wx-sortable-list__content{min-width:0}.wx-catalog-gallery__item[data-v-fdb59e51]{display:grid;grid-template-columns:72px minmax(0,1fr);gap:var(--wx-space-12);align-items:center}.wx-catalog-gallery__thumb[data-v-fdb59e51]{position:relative;display:block;width:72px;aspect-ratio:1;overflow:clip;border-radius:var(--wx-radius-sm);background:var(--wx-bg-subtle);border:1px solid var(--wx-border-default)}.wx-catalog-gallery__thumb img[data-v-fdb59e51]{width:100%;height:100%;min-width:0;object-fit:contain;display:block}.wx-catalog-gallery__main[data-v-fdb59e51]{position:absolute;inset-inline-start:var(--wx-space-2);inset-block-start:var(--wx-space-2)}.wx-catalog-gallery__size[data-v-fdb59e51],.wx-catalog-gallery__play[data-v-fdb59e51]{position:absolute;background:var(--wx-bg-overlay);color:var(--wx-color-white);font-size:var(--wx-font-size-xs);line-height:1.2;white-space:nowrap;font-variant-numeric:tabular-nums}.wx-catalog-gallery__size[data-v-fdb59e51]{inset-inline:0;inset-block-end:0;padding-block:var(--wx-space-2);text-align:center}.wx-catalog-gallery__play[data-v-fdb59e51]{inset-block-start:50%;inset-inline-start:50%;translate:-50% -50%;padding:var(--wx-space-2) var(--wx-space-4);border-radius:var(--wx-radius-xs)}.wx-catalog-gallery__body[data-v-fdb59e51]{display:flex;flex-direction:column;gap:var(--wx-space-8);min-width:0}.wx-catalog-gallery__words[data-v-fdb59e51]{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--wx-space-8)}@container (min-width: 640px){.wx-catalog-gallery__words[data-v-fdb59e51]{grid-template-columns:repeat(2,minmax(0,1fr))}}@container (max-width: 420px){.wx-catalog-gallery__item[data-v-fdb59e51]{grid-template-columns:minmax(0,1fr)}}.wx-catalog-gallery__pending[data-v-fdb59e51]{display:flex;flex-direction:column;gap:var(--wx-space-8);margin:0;padding:var(--wx-space-8) var(--wx-space-12);list-style:none;border:1px dashed var(--wx-border-default);border-radius:var(--wx-radius-md)}.wx-catalog-gallery__name[data-v-fdb59e51]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wx-catalog-gallery__picker[data-v-fdb59e51]{display:none}.wx-catalog-gallery__address[data-v-fdb59e51]{display:flex;gap:var(--wx-space-8);align-items:center;max-width:560px}.wx-catalog-gallery__address[data-v-fdb59e51]>:first-child{flex:1;min-width:0}.wx-catalog-gallery__address-hint[data-v-fdb59e51]{display:block;margin-block-start:var(--wx-space-8)}.wx-catalog-product[data-v-923c09f7]{display:flex;flex-direction:column;gap:var(--wx-gap, var(--wx-space-16));container-type:inline-size}.wx-catalog-product__ghost[data-v-923c09f7]{max-width:420px}.wx-catalog-bulk-params__field[data-v-0c68389e]{margin-top:var(--wx-space-16)}.wx-catalog-bulk[data-v-94557c14]{display:contents}.wx-catalog-bulk__progress[data-v-94557c14]{display:grid;gap:var(--wx-space-4);flex:1 1 240px;min-width:0}.wx-catalog-bulk__refused[data-v-94557c14]{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--wx-space-8);flex-basis:100%;min-width:0}.wx-catalog-bulk__errors[data-v-94557c14]{flex-basis:100%;font-size:var(--wx-font-size-sm)}.wx-catalog-bulk__errors summary[data-v-94557c14]{cursor:pointer;color:var(--wx-text-muted)}.wx-catalog-bulk__errors ul[data-v-94557c14]{margin:var(--wx-space-8) 0 0;padding-inline-start:var(--wx-space-18);max-height:200px;overflow:auto}.wx-catalog-column-value[data-v-2389d2f9]{display:inline-flex;flex-wrap:wrap;align-items:center;gap:var(--wx-space-4);min-width:0;max-width:100%}.wx-catalog-column-value.is-empty[data-v-2389d2f9]{color:var(--wx-text-muted)}.wx-catalog-products[data-v-790ab4c0]{min-width:0}.wx-catalog-products__selection[data-v-790ab4c0]{display:flex;flex-wrap:wrap;align-items:center;gap:var(--wx-space-12);padding:var(--wx-space-8) var(--wx-space-16);border-bottom:1px solid var(--wx-border-default);background:var(--wx-bg-subtle)}.wx-catalog-products__image[data-v-790ab4c0]{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--wx-radius-sm);overflow:clip;background:var(--wx-bg-subtle);color:var(--wx-text-muted);vertical-align:middle}.wx-catalog-products__image img[data-v-790ab4c0]{width:100%;height:100%;min-width:0;object-fit:cover}.wx-catalog-products__name[data-v-790ab4c0]{display:flex;flex-direction:column;min-width:0}.wx-catalog-products__title[data-v-790ab4c0]{font-weight:var(--wx-font-weight-medium);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wx-catalog-products__sku[data-v-790ab4c0]{font-family:var(--wx-font-family-mono);font-size:var(--wx-font-size-sm);color:var(--wx-text-muted);min-height:1em}.wx-catalog-products__price[data-v-790ab4c0]{display:inline-flex;flex-direction:column;align-items:flex-end;font-variant-numeric:tabular-nums}.wx-catalog-products__price[data-v-790ab4c0]>*{white-space:nowrap}.wx-catalog-products__price small[data-v-790ab4c0],.wx-catalog-products__price s[data-v-790ab4c0]{font-size:var(--wx-font-size-sm);color:var(--wx-text-muted)}.wx-catalog-products__range[data-v-790ab4c0]{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--wx-space-8)}.wx-catalog-tone[data-v-2b8d13bb]{display:flex;flex-wrap:wrap;align-items:center;gap:var(--wx-space-12)}.wx-catalog-tone__choices[data-v-2b8d13bb]{display:flex;flex-wrap:wrap;gap:var(--wx-space-6)}.wx-catalog-tone__choice[data-v-2b8d13bb]{display:inline-flex;padding:0;border:0;border-radius:var(--wx-radius-full);background:none;font:inherit;cursor:pointer}.wx-catalog-tone__choice[data-v-2b8d13bb]:disabled{cursor:not-allowed;opacity:.6}.wx-catalog-tone__choice[data-v-2b8d13bb]:focus-visible{outline:2px solid var(--wx-border-focus);outline-offset:2px}.wx-catalog-tone__sample[data-v-2b8d13bb]{display:inline-flex;padding-left:var(--wx-space-12);border-left:1px solid var(--wx-border-default)}
@@ -0,0 +1,10 @@
1
+ import { BadgeType } from '@webx-ui/core';
2
+ /**
3
+ * The six tones a record of a reference book is painted in (labels, stock statuses) — the
4
+ * server's `Dictionary::TONES`. A tone and not a colour: the site puts it into a class, the panel
5
+ * into a tag of the same tone, and nobody writes a hex anywhere.
6
+ */
7
+ export declare const TONES: readonly ["neutral", "primary", "success", "warning", "danger", "info"];
8
+ export type Tone = (typeof TONES)[number];
9
+ /** The tag the panel draws a tone as. `neutral` is the core's `default`; the rest match by name. */
10
+ export declare function toneBadge(tone: unknown): BadgeType;
package/dist/types.d.ts CHANGED
@@ -45,10 +45,24 @@ export interface ProductRow {
45
45
  updated_at: string | null;
46
46
  deleted_at: string | null;
47
47
  /** The satellites' columns (`ProductColumns`), by key. Absent while none is installed. */
48
- columns?: Record<string, string | number | boolean | null>;
48
+ columns?: Record<string, ColumnValue>;
49
49
  /** A row of `WxTable`, which reads cells by key. */
50
50
  [key: string]: unknown;
51
51
  }
52
+ /**
53
+ * What a satellite's column holds for one product: words, or a record by name — with a tone
54
+ * (`{ name, color }`, a stock status), or taken off the site (`{ name, visible: false }`, a brand) —
55
+ * or a list of those (labels). `ColumnValue.vue` draws each by its shape.
56
+ */
57
+ export type ColumnValue = string | number | boolean | null | ColumnRecord | ColumnRecord[];
58
+ export interface ColumnRecord {
59
+ id?: number | string;
60
+ name: string;
61
+ /** One of the six tones (`tones.ts`). */
62
+ color?: string | null;
63
+ visible?: boolean;
64
+ [key: string]: unknown;
65
+ }
52
66
  /** A column a satellite adds to the list (§7.4). The values ride on each row under its key. */
53
67
  export interface ProductColumnInfo {
54
68
  key: string;
@@ -117,6 +131,30 @@ export interface ProductImage {
117
131
  height: number | null;
118
132
  size: number | null;
119
133
  position: number;
134
+ /** The video attached to the picture, which is then its poster (the video spec, §1.1). */
135
+ video?: ProductVideo | null;
136
+ }
137
+ /** A video in the gallery: a file on the gallery's disk, or one on a provider's site. */
138
+ export interface ProductVideo {
139
+ /** `file`, or the provider's key (`youtube`). */
140
+ provider: string;
141
+ /** The file, or the provider's page of the video. */
142
+ url: string;
143
+ /** The address for an iframe; `null` for a file. */
144
+ embed: string | null;
145
+ /** Whole seconds, when known. */
146
+ duration: number | null;
147
+ }
148
+ /**
149
+ * The answer to a direct link to a video file: the server downloads it in its queue, and the row
150
+ * appears — or the picture gets its video — when that is done.
151
+ */
152
+ export interface QueuedVideo {
153
+ queued: true;
154
+ product: number;
155
+ url: string;
156
+ /** The picture the video goes onto; `null` for a new row. */
157
+ image: number | null;
120
158
  }
121
159
  /** One product as its editor opens it. */
122
160
  export interface ProductDetail {
@@ -225,6 +263,8 @@ export interface BulkParam {
225
263
  value: string | number;
226
264
  label: string;
227
265
  }> | string;
266
+ /** Where the panel asks for the values instead: a reference book's path (`catalog/labels`). */
267
+ source?: string;
228
268
  }
229
269
  /** One bulk action the server offers this administrator (§11.4): the core's or a satellite's. */
230
270
  export interface BulkActionInfo {
@@ -0,0 +1,69 @@
1
+ import { ProductImage } from './types';
2
+ /**
3
+ * The browser half of videos in the gallery (§1.6, §7 of the video spec): the frame that becomes
4
+ * the poster, and the checks made before a byte is sent.
5
+ */
6
+ /** What the panel learns about a video file by opening it in the browser. */
7
+ export interface VideoProbe {
8
+ /** The frame, as a JPEG; `null` when only the length was asked for. */
9
+ frame: Blob | null;
10
+ /** Whole seconds, or `null` when the file does not say. */
11
+ duration: number | null;
12
+ width: number;
13
+ height: number;
14
+ }
15
+ /**
16
+ * The pieces of the DOM the probe needs, handed in so that a test can stand them up: jsdom does
17
+ * not decode video, so a probe against a real `<video>` there never gets past loading.
18
+ */
19
+ export interface ProbeEnvironment {
20
+ createVideo(): HTMLVideoElement;
21
+ createCanvas(): HTMLCanvasElement;
22
+ createUrl(file: Blob): string;
23
+ revokeUrl(url: string): void;
24
+ }
25
+ export interface ProbeOptions {
26
+ /** Take a frame as well as the length. */
27
+ frame?: boolean;
28
+ /** How long to wait for the browser to open the file before giving up on it. */
29
+ timeout?: number;
30
+ environment?: ProbeEnvironment;
31
+ }
32
+ /** The browser could not open the file — mostly a codec it does not play. */
33
+ export declare class VideoUnreadable extends Error {
34
+ constructor(reason: string);
35
+ }
36
+ /** Where the frame is taken: a little in, as the very first frame is so often black. */
37
+ export declare function frameTime(duration: number): number;
38
+ /**
39
+ * Open a video file in the browser and read its length and, if asked, one frame of it.
40
+ *
41
+ * Read off the local file, before the upload, so a poster does not wait on gigabytes going up
42
+ * (decision 6). Rejects with `VideoUnreadable` when the browser cannot open the file, which is
43
+ * what the panel then says in words: add a picture and attach the video to it.
44
+ */
45
+ export declare function probeVideo(file: Blob, options?: ProbeOptions): Promise<VideoProbe>;
46
+ /** The name of the poster: the video's own, as a JPEG. */
47
+ export declare function posterName(file: Pick<File, 'name'>): string;
48
+ /**
49
+ * The id of a YouTube video in any of the forms the server takes (§3), or `null`. The server
50
+ * decides in the end; this only says what the field should call the address.
51
+ */
52
+ export declare function youTubeId(address: string): string | null;
53
+ /** A direct link to an MP4 or WebM file, judged by its name — the server checks the answer. */
54
+ export declare function isVideoFileLink(address: string): boolean;
55
+ /** Anything the gallery treats as a video rather than a picture. */
56
+ export declare function isVideoLink(address: string): boolean;
57
+ /** A file the gallery may take as a video, by the limits the screen gave it. */
58
+ export declare function videoRefusal(file: Pick<File, 'type' | 'size'>, types: readonly string[], maxBytes: number): 'type' | 'size' | null;
59
+ /**
60
+ * The poster the server puts on a video that came by a direct link without a picture: a plain
61
+ * dark PNG, 1280×720 (a single pixel where the server has no GD). Recognised by its shape, as the
62
+ * resource carries no mark of it; a panel-made poster is a JPEG, so a mistake here needs a PNG of
63
+ * exactly that size with a file video on it, and then the hint only says what may be done anyway.
64
+ */
65
+ export declare function hasPlaceholderPoster(image: ProductImage): boolean;
66
+ /** Bytes as the panel says them: "840 KB", "1.2 GB". */
67
+ export declare function formatBytes(bytes: number, locale?: string): string;
68
+ /** A length of time as a clock: "0:42", "12:05", "1:02:03". */
69
+ export declare function formatClock(seconds: number): string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webx-ui/module-catalog",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "The catalogue of the WebX UI admin panel: products with a gallery, a tree of categories with their filters, and the deleted ones waiting to come back.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -44,8 +44,8 @@
44
44
  "vue-router": "^4.5.0"
45
45
  },
46
46
  "dependencies": {
47
- "@webx-ui/core": "^0.34.1",
48
- "@webx-ui/module-admin": "^0.19.0",
47
+ "@webx-ui/core": "^0.34.2",
48
+ "@webx-ui/module-admin": "^0.21.0",
49
49
  "@webx-ui/schema": "^0.6.4"
50
50
  },
51
51
  "devDependencies": {