neba 1.3.0 → 1.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/README.md +4 -6
- package/dist/components/data-table/DataTable.d.ts +323 -0
- package/dist/components/data-table/DataTable.js +1 -0
- package/dist/components/data-table/index.d.ts +2 -0
- package/dist/components/data-table/index.js +1 -0
- package/dist/components/empty/Empty.d.ts +69 -0
- package/dist/components/empty/Empty.js +1 -0
- package/dist/components/empty/index.d.ts +2 -0
- package/dist/components/empty/index.js +1 -0
- package/dist/components/mockup/Mockup.d.ts +151 -0
- package/dist/components/mockup/Mockup.js +1 -0
- package/dist/components/mockup/index.d.ts +2 -0
- package/dist/components/mockup/index.js +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +1 -1
- package/dist/internal/data-table.d.ts +170 -0
- package/dist/internal/data-table.js +1 -0
- package/dist/internal/i18n.d.ts +51 -0
- package/dist/internal/i18n.js +1 -1
- package/dist/internal/mockup.d.ts +193 -0
- package/dist/internal/mockup.js +1 -0
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +26 -11
- package/package.json +6 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t,Fragment as i}from"react/jsx-runtime";import*as r from"react";import{useRender as n}from"@base-ui/react/use-render";import{transitionProps as a}from"../../internal/animate";import{MockupCutout as o,defaultNotch as s,elevationFilters as d,finishSlots as h,mockupChrome as l,mockupMetrics as c,resolveOs as u,shellClasses as f}from"../../internal/mockup";import{surfaceSlots as m}from"../../internal/styles";const p="undefined"==typeof document?r.useEffect:r.useLayoutEffect;export const Mockup=r.forwardRef(function({device:g,os:b,hardware:v="monitor",size:w="md",resolution:y,orientation:x="portrait",bezel:k="standard",finish:R="graphite",notch:N,systemUi:z=!0,scroll:$=!1,wallpaper:M,time:j="9:41",width:W,height:B,color:H="primary",elevation:C=0,transition:E,render:L,className:O,style:P,children:S,...F},I){const T=u(g,b),U=N??s(g,T),q="desktop"!==g&&"landscape"===x,A=c({device:g,size:w,resolution:y,orientation:x,bezel:k,hardware:v}),{screen:D,frame:G,body:J,stand:K,base:Q}=A,V=r.useRef(null),[X,Y]=r.useState(null);p(()=>{const e=V.current;if(!e)return;const t=()=>{const t=e.getBoundingClientRect();if(t.width<=0||t.height<=0)return;const i=Math.min(t.width/G.width,t.height/G.height);Y(e=>null!==e&&Math.abs(e-i)<1e-4?e:i)};if(t(),"undefined"==typeof ResizeObserver)return;const i=new ResizeObserver(t);return i.observe(e),()=>i.disconnect()},[G.width,G.height]);const Z=r.useCallback(e=>{V.current=e,"function"==typeof I?I(e):I&&(I.current=e)},[I]),_=z?l({os:T,notch:U,landscape:q,time:j}):{},ee=a(E),te="none"===k,ie=t("div",{className:"neba-mockup-screen relative flex flex-col overflow-hidden",style:{width:D.width,height:D.height,borderRadius:A.screenRadius,background:M??"var(--neba-surface)",boxShadow:te?void 0:"inset 0 0 0 1px var(--n-shell-shade)"},children:[_.top?.node,t("div",{className:"flex min-h-0 flex-1",children:[_.start?.node,e("div",{className:"min-w-0 flex-1 "+($?"overflow-auto":"overflow-hidden"),style:{containerType:"size",containerName:"neba-screen"},children:S})]}),_.bottom?.node,e(o,{notch:U,screen:D,landscape:q})]}),re=["neba-mockup relative block",ee.className,O??""].filter(Boolean).join(" ");return n({render:L,ref:Z,props:{className:re,style:{...m(H,C),...h[R],...ee.style,width:W??(void 0===B?"100%":"auto"),height:B??"auto",aspectRatio:`${G.width} / ${G.height}`,filter:d[C],...P},children:t("div",{className:"absolute top-1/2 left-1/2 flex flex-col items-center",style:{width:G.width,height:G.height,transform:`translate(-50%, -50%) scale(${X??1})`,visibility:null===X?"hidden":void 0},children:[e("div",{className:te?"":f,style:{width:J.width,height:J.height,borderRadius:A.frameRadius,paddingBlock:`${A.bezel.top}px ${A.bezel.bottom}px`,paddingInline:A.bezel.x},children:ie}),K?t(i,{children:[e("div",{"aria-hidden":"true",style:{width:K.neckWidth,height:K.neckHeight,background:"var(--n-shell-shade)",clipPath:"polygon(16% 0, 84% 0, 100% 100%, 0 100%)"}}),e("div",{"aria-hidden":"true",className:f,style:{width:K.footWidth,height:K.footHeight,borderRadius:K.footHeight/2}})]}):null,Q?e("div",{"aria-hidden":"true",className:`relative ${f}`,style:{width:Q.width,height:Q.height,borderRadius:`0 0 ${Math.round(.55*Q.height)}px ${Math.round(.55*Q.height)}px`,clipPath:"polygon(0 0, 100% 0, 98.5% 100%, 1.5% 100%)"},children:e("div",{className:"absolute top-0 left-1/2",style:{width:Q.lipWidth,height:Math.round(.34*Q.height),marginLeft:-Q.lipWidth/2,borderRadius:`0 0 ${Math.round(.2*Q.height)}px ${Math.round(.2*Q.height)}px`,background:"var(--n-shell-shade)"}})}):null]}),...F}})});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{Mockup}from"./Mockup";
|
package/dist/index.d.ts
CHANGED
|
@@ -28,12 +28,14 @@ export * from './components/chip';
|
|
|
28
28
|
export * from './components/color-picker';
|
|
29
29
|
export * from './components/combobox';
|
|
30
30
|
export * from './components/container';
|
|
31
|
+
export * from './components/data-table';
|
|
31
32
|
export * from './components/date-picker';
|
|
32
33
|
export * from './components/date-range-picker';
|
|
33
34
|
export * from './components/date-time-picker';
|
|
34
35
|
export * from './components/dialog';
|
|
35
36
|
export * from './components/divider';
|
|
36
37
|
export * from './components/drawer';
|
|
38
|
+
export * from './components/empty';
|
|
37
39
|
export * from './components/file-picker';
|
|
38
40
|
export * from './components/grid';
|
|
39
41
|
export * from './components/grid-container';
|
|
@@ -42,6 +44,7 @@ export * from './components/icon';
|
|
|
42
44
|
export * from './components/icon-button';
|
|
43
45
|
export * from './components/list';
|
|
44
46
|
export * from './components/menu';
|
|
47
|
+
export * from './components/mockup';
|
|
45
48
|
export * from './components/number-field';
|
|
46
49
|
export * from './components/otp-field';
|
|
47
50
|
export * from './components/overlay';
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./types";export*from"./components/accordion";export*from"./components/alert";export*from"./components/animate-appear";export*from"./components/animate-blink";export*from"./components/animate-fade";export*from"./components/animate-grow";export*from"./components/animate-headline";export*from"./components/animate-lighting";export*from"./components/animate-marquee";export*from"./components/animate-rotate";export*from"./components/animate-slide";export*from"./components/animate-typing";export*from"./components/animate-zoom";export*from"./components/aspect-ratio";export*from"./components/avatar";export*from"./components/badge";export*from"./components/blockquote";export*from"./components/box";export*from"./components/breadcrumb";export*from"./components/button";export*from"./components/button-group";export*from"./components/card";export*from"./components/carousel";export*from"./components/chat-bubble";export*from"./components/checkbox";export*from"./components/chip";export*from"./components/color-picker";export*from"./components/combobox";export*from"./components/container";export*from"./components/date-picker";export*from"./components/date-range-picker";export*from"./components/date-time-picker";export*from"./components/dialog";export*from"./components/divider";export*from"./components/drawer";export*from"./components/file-picker";export*from"./components/grid";export*from"./components/grid-container";export*from"./components/highlight";export*from"./components/icon";export*from"./components/icon-button";export*from"./components/list";export*from"./components/menu";export*from"./components/number-field";export*from"./components/otp-field";export*from"./components/overlay";export*from"./components/pagination";export*from"./components/panes";export*from"./components/pill";export*from"./components/popover";export*from"./components/progress-box";export*from"./components/progress-circular";export*from"./components/progress-linear";export*from"./components/radio-group";export*from"./components/segmented-button";export*from"./components/select";export*from"./components/shortcut";export*from"./components/skeleton";export*from"./components/slider";export*from"./components/spoiler";export*from"./components/statistic";export*from"./components/switch";export*from"./components/table";export*from"./components/tabs";export*from"./components/text-field";export*from"./components/text-link";export*from"./components/time-picker";export*from"./components/timeline";export*from"./components/toast";export*from"./components/toolbar";export*from"./components/tooltip";export*from"./components/tree-view";export*from"./components/typography";
|
|
1
|
+
export*from"./types";export*from"./components/accordion";export*from"./components/alert";export*from"./components/animate-appear";export*from"./components/animate-blink";export*from"./components/animate-fade";export*from"./components/animate-grow";export*from"./components/animate-headline";export*from"./components/animate-lighting";export*from"./components/animate-marquee";export*from"./components/animate-rotate";export*from"./components/animate-slide";export*from"./components/animate-typing";export*from"./components/animate-zoom";export*from"./components/aspect-ratio";export*from"./components/avatar";export*from"./components/badge";export*from"./components/blockquote";export*from"./components/box";export*from"./components/breadcrumb";export*from"./components/button";export*from"./components/button-group";export*from"./components/card";export*from"./components/carousel";export*from"./components/chat-bubble";export*from"./components/checkbox";export*from"./components/chip";export*from"./components/color-picker";export*from"./components/combobox";export*from"./components/container";export*from"./components/data-table";export*from"./components/date-picker";export*from"./components/date-range-picker";export*from"./components/date-time-picker";export*from"./components/dialog";export*from"./components/divider";export*from"./components/drawer";export*from"./components/empty";export*from"./components/file-picker";export*from"./components/grid";export*from"./components/grid-container";export*from"./components/highlight";export*from"./components/icon";export*from"./components/icon-button";export*from"./components/list";export*from"./components/menu";export*from"./components/mockup";export*from"./components/number-field";export*from"./components/otp-field";export*from"./components/overlay";export*from"./components/pagination";export*from"./components/panes";export*from"./components/pill";export*from"./components/popover";export*from"./components/progress-box";export*from"./components/progress-circular";export*from"./components/progress-linear";export*from"./components/radio-group";export*from"./components/segmented-button";export*from"./components/select";export*from"./components/shortcut";export*from"./components/skeleton";export*from"./components/slider";export*from"./components/spoiler";export*from"./components/statistic";export*from"./components/switch";export*from"./components/table";export*from"./components/tabs";export*from"./components/text-field";export*from"./components/text-link";export*from"./components/time-picker";export*from"./components/timeline";export*from"./components/toast";export*from"./components/toolbar";export*from"./components/tooltip";export*from"./components/tree-view";export*from"./components/typography";
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The arithmetic a DataTable is made of.
|
|
3
|
+
*
|
|
4
|
+
* Here rather than in the component for the reason `progress.ts` and `color.ts`
|
|
5
|
+
* are here: none of it is layout and none of it is a class name. Sorting rows,
|
|
6
|
+
* matching a query against them, cutting a page out of the result and working
|
|
7
|
+
* out which twenty of forty thousand rows are actually on screen are four
|
|
8
|
+
* questions with numeric answers, and a component file that also has to draw a
|
|
9
|
+
* resize handle is not where they can be read.
|
|
10
|
+
*
|
|
11
|
+
* `color.ts` is the precedent for a single-consumer file: the test is whether
|
|
12
|
+
* the thing is separable, not whether two components happen to want it. Every
|
|
13
|
+
* function below takes plain values and returns plain values — there is no
|
|
14
|
+
* React in this file, and nothing in it knows what a column is.
|
|
15
|
+
*/
|
|
16
|
+
import type { NebaDensity, NebaSize } from '../types';
|
|
17
|
+
/**
|
|
18
|
+
* Row height, in **pixels**, and the one number in the library that has to be a
|
|
19
|
+
* number rather than a class.
|
|
20
|
+
*
|
|
21
|
+
* Virtual scrolling is arithmetic on this value: how far down the list a scroll
|
|
22
|
+
* offset lands, how tall the spacer above the first rendered row is, how many
|
|
23
|
+
* rows fit in the viewport for PageDown. A Tailwind class cannot be added up.
|
|
24
|
+
*
|
|
25
|
+
* The ladder is deliberately below `controlHeightClasses` at every step — 28px
|
|
26
|
+
* at `md` against a Button's 32 — because a DataTable is a hundred rows on one
|
|
27
|
+
* screen and a Table is eight. A row here is the height of the text plus enough
|
|
28
|
+
* air to click, and nothing more; `density` is what takes the last of the air
|
|
29
|
+
* out. A caller who puts a Chip or an Avatar in a cell raises `rowHeight`.
|
|
30
|
+
*/
|
|
31
|
+
export declare const dataRowHeights: Record<NebaDensity, Record<NebaSize, number>>;
|
|
32
|
+
/**
|
|
33
|
+
* The header, one step taller than the rows under it.
|
|
34
|
+
*
|
|
35
|
+
* A fixed number rather than "whatever the content measures", because a sticky
|
|
36
|
+
* header over a group row needs an offset to stick the second row at, and a
|
|
37
|
+
* measured one would be a layout read on every scroll frame.
|
|
38
|
+
*/
|
|
39
|
+
export declare const dataHeaderHeights: Record<NebaDensity, Record<NebaSize, number>>;
|
|
40
|
+
/**
|
|
41
|
+
* The tick column, and the resize handle's grab area.
|
|
42
|
+
*
|
|
43
|
+
* The tick column is `tickSizeClasses` plus the two padding tracks, rounded to
|
|
44
|
+
* a whole pixel: a column narrower than the box in it clips the focus ring.
|
|
45
|
+
*/
|
|
46
|
+
export declare const dataTickWidths: Record<NebaSize, number>;
|
|
47
|
+
/** How wide a column is when neither the caller nor a drag has said. */
|
|
48
|
+
export declare const defaultColumnWidth = 160;
|
|
49
|
+
/** How narrow a drag may make one. Below this the heading is a single letter. */
|
|
50
|
+
export declare const minColumnWidth = 48;
|
|
51
|
+
export type SortDirection = 'asc' | 'desc';
|
|
52
|
+
/** One key of a sort, and which way it runs. */
|
|
53
|
+
export interface SortEntry {
|
|
54
|
+
key: string;
|
|
55
|
+
direction: SortDirection;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The default comparison, for the columns that do not bring one.
|
|
59
|
+
*
|
|
60
|
+
* Empty sorts last in both directions, which is the one asymmetry here and the
|
|
61
|
+
* one every spreadsheet has: a blank is not the smallest value, it is the
|
|
62
|
+
* absence of one, and a descending sort whose first screen is forty blanks has
|
|
63
|
+
* answered the wrong question.
|
|
64
|
+
*
|
|
65
|
+
* Numbers compare as numbers, dates as instants, booleans with `false` first,
|
|
66
|
+
* and everything else through the collator — which is `numeric`, so `item2`
|
|
67
|
+
* comes before `item10` rather than after it.
|
|
68
|
+
*/
|
|
69
|
+
export declare function compareValues(a: unknown, b: unknown, collator: Intl.Collator): number;
|
|
70
|
+
/**
|
|
71
|
+
* Sorts by every key at once, first key outermost.
|
|
72
|
+
*
|
|
73
|
+
* The sort is **stable** — `Array.prototype.sort` has been since ES2019 — which
|
|
74
|
+
* is what makes a multi-key sort composable: sorting by name and then adding
|
|
75
|
+
* date to the end of the list leaves rows with the same date in name order,
|
|
76
|
+
* because that is the order they were already in.
|
|
77
|
+
*
|
|
78
|
+
* `comparatorFor` returns `null` for a key no column claims, so a sort left
|
|
79
|
+
* over from a column that has since been removed is skipped rather than
|
|
80
|
+
* throwing.
|
|
81
|
+
*/
|
|
82
|
+
export declare function sortRows<T>(rows: readonly T[], sort: readonly SortEntry[], comparatorFor: (key: string) => ((a: T, b: T) => number) | null): T[];
|
|
83
|
+
/**
|
|
84
|
+
* What pressing a heading does, given what the sort already says.
|
|
85
|
+
*
|
|
86
|
+
* Three states rather than two — ascending, descending, unsorted — because the
|
|
87
|
+
* order the rows arrived in is a state a caller cannot get back to by pressing
|
|
88
|
+
* anything if the cycle only has two. This is the opposite of the choice
|
|
89
|
+
* TreeView's single select makes, and for the same reason: there, "nothing
|
|
90
|
+
* chosen" is reachable by pressing something else; here it is not.
|
|
91
|
+
*
|
|
92
|
+
* `additive` is what a Shift-click sets. It keeps the column where it already
|
|
93
|
+
* is in the list rather than moving it to the end, so flipping the second key
|
|
94
|
+
* of a two-key sort does not silently make it the first.
|
|
95
|
+
*/
|
|
96
|
+
export declare function nextSort(current: readonly SortEntry[], key: string, additive: boolean): SortEntry[];
|
|
97
|
+
/**
|
|
98
|
+
* A cell value as something a query can be matched against.
|
|
99
|
+
*
|
|
100
|
+
* Case-folded and stripped of combining marks, so `jose` finds `José` and
|
|
101
|
+
* `SEOUL` finds `Seoul`. `NFD` splits an accented letter into the letter and
|
|
102
|
+
* its accent and the range then deletes the accent; a search field is the one
|
|
103
|
+
* place where losing that distinction is the point.
|
|
104
|
+
*
|
|
105
|
+
* A `Date` is deliberately *not* formatted here. What a reader sees in the cell
|
|
106
|
+
* came out of the caller's `render`, and guessing a format the search would
|
|
107
|
+
* agree with is how a table ends up not finding a date that is on the screen —
|
|
108
|
+
* a column that wants its dates searchable gives them a `value`.
|
|
109
|
+
*/
|
|
110
|
+
export declare function searchText(value: unknown): string;
|
|
111
|
+
/** Where one page starts and stops, and how many there are. */
|
|
112
|
+
export interface PageBounds {
|
|
113
|
+
/** How many pages the rows come to. Never below `1`. */
|
|
114
|
+
pages: number;
|
|
115
|
+
/** The page actually shown, clamped into range. */
|
|
116
|
+
page: number;
|
|
117
|
+
/** Index of the first row on it. */
|
|
118
|
+
start: number;
|
|
119
|
+
/** One past the last. */
|
|
120
|
+
end: number;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The page arithmetic, with the clamp in it.
|
|
124
|
+
*
|
|
125
|
+
* The clamp is the whole reason this is a function: a filter that cuts a
|
|
126
|
+
* twenty-page table to three leaves the caller's `page` at 14, and a table that
|
|
127
|
+
* answers with an empty screen has told the reader their search found nothing.
|
|
128
|
+
* The page moves to the last one that exists instead.
|
|
129
|
+
*/
|
|
130
|
+
export declare function pageBounds(total: number, page: number, pageSize: number): PageBounds;
|
|
131
|
+
/** Which rows are rendered, and how much empty space stands in for the rest. */
|
|
132
|
+
export interface VirtualWindow {
|
|
133
|
+
/** Index of the first row rendered. */
|
|
134
|
+
start: number;
|
|
135
|
+
/** One past the last. */
|
|
136
|
+
end: number;
|
|
137
|
+
/** The height of the spacer row above, in pixels. */
|
|
138
|
+
before: number;
|
|
139
|
+
/** And of the one below. */
|
|
140
|
+
after: number;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* The rows a scroll offset puts on screen, plus a margin either side.
|
|
144
|
+
*
|
|
145
|
+
* Two spacer rows rather than a translated `<tbody>`: a transform on the body
|
|
146
|
+
* of a table breaks `position: sticky` on the header above it, and the library
|
|
147
|
+
* has a rule about transforms anyway. Padding is also what keeps the scrollbar
|
|
148
|
+
* honest — the scroll height is the real one, so dragging the thumb to the
|
|
149
|
+
* middle lands in the middle of the data.
|
|
150
|
+
*
|
|
151
|
+
* `viewport` of `0` is the first render, before anything has been measured. It
|
|
152
|
+
* cannot mean "no rows" — the layout effect that measures runs after a render
|
|
153
|
+
* and there would be nothing to measure — so it renders a screen's worth on
|
|
154
|
+
* spec and corrects before the frame is painted.
|
|
155
|
+
*/
|
|
156
|
+
export declare function virtualWindow(scrollTop: number, viewport: number, rowHeight: number, count: number, overscan: number): VirtualWindow;
|
|
157
|
+
/**
|
|
158
|
+
* Every key between two, inclusive, in the order the rows are currently in.
|
|
159
|
+
*
|
|
160
|
+
* "Currently" is the point: a Shift-click selects what the reader can see
|
|
161
|
+
* between the two rows they clicked, so the range is taken from the sorted,
|
|
162
|
+
* filtered order rather than from the order `items` arrived in. Which of the
|
|
163
|
+
* two keys is the anchor does not matter — dragging up selects the same rows as
|
|
164
|
+
* dragging down.
|
|
165
|
+
*
|
|
166
|
+
* A key that is no longer in the list (a row the current filter hides) yields
|
|
167
|
+
* an empty range rather than a range from one end, which is what an index of
|
|
168
|
+
* `-1` would silently produce.
|
|
169
|
+
*/
|
|
170
|
+
export declare function keysBetween(order: readonly string[], from: string, to: string): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const dataRowHeights={default:{xs:24,sm:28,md:32,lg:38,xl:44},compact:{xs:20,sm:24,md:28,lg:32,xl:38}};export const dataHeaderHeights={default:{xs:28,sm:32,md:36,lg:42,xl:48},compact:{xs:24,sm:28,md:32,lg:36,xl:42}};export const dataTickWidths={xs:30,sm:34,md:38,lg:42,xl:50};export const defaultColumnWidth=160;export const minColumnWidth=48;export function compareValues(t,e,n){const o=null==t||""===t,r=null==e||""===e;return o||r?o&&r?0:o?1:-1:"number"==typeof t&&"number"==typeof e?Number.isNaN(t)||Number.isNaN(e)?Number.isNaN(t)&&Number.isNaN(e)?0:Number.isNaN(t)?1:-1:t-e:"boolean"==typeof t&&"boolean"==typeof e?Number(t)-Number(e):t instanceof Date&&e instanceof Date?t.getTime()-e.getTime():n.compare(String(t),String(e))}export function sortRows(t,e,n){if(0===e.length)return t;const o=e.map(t=>{const e=n(t.key);return e?{compare:e,sign:"desc"===t.direction?-1:1}:null}).filter(t=>null!==t);return 0===o.length?t:[...t].sort((t,e)=>{for(const n of o){const o=n.compare(t,e);if(0!==o)return o*n.sign}return 0})}export function nextSort(t,e,n){const o=t.find(t=>t.key===e),r=void 0===o?"asc":"asc"===o.direction?"desc":null;return n?null===r?t.filter(t=>t.key!==e):void 0===o?[...t,{key:e,direction:r}]:t.map(t=>t.key===e?{key:e,direction:r}:t):null===r?[]:[{key:e,direction:r}]}export function searchText(t){return null==t||"object"==typeof t?"":String(t).normalize("NFD").replace(/[\u0300-\u036f]/g,"").toLowerCase()}export function pageBounds(t,e,n){const o=Math.max(1,Math.floor(n)),r=Math.max(1,Math.ceil(t/o)),a=Math.min(Math.max(Math.floor(e),1),r),i=(a-1)*o;return{pages:r,page:a,start:i,end:Math.min(i+o,t)}}export function virtualWindow(t,e,n,o,r){const a=e>0?Math.ceil(e/n):3*r,i=Math.max(0,Math.floor(t/n)-r),s=Math.min(o,i+a+2*r);return{start:i,end:s,before:i*n,after:Math.max(0,(o-s)*n)}}export function keysBetween(t,e,n){const o=t.indexOf(e),r=t.indexOf(n);return-1===o||-1===r?[]:t.slice(Math.min(o,r),Math.max(o,r)+1)}
|
package/dist/internal/i18n.d.ts
CHANGED
|
@@ -62,6 +62,46 @@ export interface NebaMessages {
|
|
|
62
62
|
/** What the three dots mean. */
|
|
63
63
|
typing: string;
|
|
64
64
|
};
|
|
65
|
+
/** Empty. */
|
|
66
|
+
empty: {
|
|
67
|
+
/**
|
|
68
|
+
* The headline over a region with nothing in it.
|
|
69
|
+
*
|
|
70
|
+
* The one string in here that is *drawn* at full size rather than read out
|
|
71
|
+
* or written on a button, and it is here for the same reason the rest are:
|
|
72
|
+
* an empty state has nothing to take its words from. What is missing is the
|
|
73
|
+
* caller's — a search, an inbox, a folder — so the default says only that
|
|
74
|
+
* there is nothing, and anything more specific is the `title` prop.
|
|
75
|
+
*/
|
|
76
|
+
title: string;
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* DataTable.
|
|
80
|
+
*
|
|
81
|
+
* A DataTable is the one component in the library that draws chrome of its
|
|
82
|
+
* own — a search field, a header tick that chooses everything at once, a
|
|
83
|
+
* footer counting what is on screen — so it is also the one that has the most
|
|
84
|
+
* to say without being handed the words.
|
|
85
|
+
*/
|
|
86
|
+
table: {
|
|
87
|
+
/** Placeholder and accessible name of the search field. */
|
|
88
|
+
search: string;
|
|
89
|
+
/** The tick in the header row, which chooses every row at once. */
|
|
90
|
+
selectAll: string;
|
|
91
|
+
/** The tick on a row. */
|
|
92
|
+
selectRow: string;
|
|
93
|
+
/** Beside the footer's page-size Select. */
|
|
94
|
+
rowsPerPage: string;
|
|
95
|
+
/**
|
|
96
|
+
* Which rows are on screen, out of how many there are. `{start}`, `{end}`
|
|
97
|
+
* and `{total}` are replaced with the numbers, already formatted for the
|
|
98
|
+
* locale — a template rather than three fragments, because the order the
|
|
99
|
+
* three appear in is exactly what differs between languages.
|
|
100
|
+
*/
|
|
101
|
+
range: string;
|
|
102
|
+
/** How many rows are chosen. `{count}` is replaced the same way. */
|
|
103
|
+
selected: string;
|
|
104
|
+
};
|
|
65
105
|
/**
|
|
66
106
|
* ColorPicker.
|
|
67
107
|
*
|
|
@@ -101,3 +141,14 @@ export interface NebaMessages {
|
|
|
101
141
|
export declare function resolveMessages(locale?: string): NebaMessages;
|
|
102
142
|
/** The same, as a hook, for the components that read it during a render. */
|
|
103
143
|
export declare function useMessages(locale?: string): NebaMessages;
|
|
144
|
+
/**
|
|
145
|
+
* Fills the `{placeholders}` in one of the strings above.
|
|
146
|
+
*
|
|
147
|
+
* Two of them carry numbers, and neither could be assembled out of fragments:
|
|
148
|
+
* "1–25 of 1,204" is "전체 1,204개 중 1–25" in Korean and "1,204 kayıttan 1–25"
|
|
149
|
+
* in Turkish, so what differs between languages is the *order*, which only a
|
|
150
|
+
* whole sentence can state. A `{name}` with no value is left alone rather than
|
|
151
|
+
* blanked, so a mistranslated placeholder shows up as itself instead of as a
|
|
152
|
+
* hole in the middle of a sentence.
|
|
153
|
+
*/
|
|
154
|
+
export declare function fillMessage(template: string, values: Record<string, string>): string;
|
package/dist/internal/i18n.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as e from"react";const a={link:{newTab:"(opens in a new tab)"},spoiler:{reveal:"Reveal",hide:"Hide",notice:"This may contain spoilers"},chat:{sending:"Sending",sent:"Sent",delivered:"Delivered",read:"Read",failed:"Not sent",typing:"Typing…"},color:{area:"Saturation and brightness",hue:"Hue",alpha:"Opacity",value:"Colour value",swatches:"Preset colours",clear:"Clear",empty:"Choose a colour"}},n={ko:{link:{newTab:"(새 창에서 열림)"},spoiler:{reveal:"내용 보기",hide:"숨기기",notice:"스포일러가 포함되어 있을 수 있습니다"},chat:{sending:"보내는 중",sent:"보냄",delivered:"전달됨",read:"읽음",failed:"전송 실패",typing:"입력 중…"},color:{area:"채도와 명도",hue:"색상",alpha:"불투명도",value:"색상 값",swatches:"기본 색상",clear:"지우기",empty:"색상 선택"}},ja:{link:{newTab:"(新しいタブで開きます)"},spoiler:{reveal:"表示する",hide:"隠す",notice:"ネタバレを含む可能性があります"},chat:{sending:"送信中",sent:"送信済み",delivered:"配信済み",read:"既読",failed:"送信できませんでした",typing:"入力中…"},color:{area:"彩度と明度",hue:"色相",alpha:"不透明度",value:"カラー値",swatches:"プリセットの色",clear:"クリア",empty:"色を選択"}},"zh-hans":{link:{newTab:"(在新标签页中打开)"},spoiler:{reveal:"显示内容",hide:"隐藏",notice:"此内容可能包含剧透"},chat:{sending:"发送中",sent:"已发送",delivered:"已送达",read:"已读",failed:"发送失败",typing:"正在输入…"},color:{area:"饱和度和明度",hue:"色相",alpha:"不透明度",value:"颜色值",swatches:"预设颜色",clear:"清除",empty:"选择颜色"}},"zh-hant":{link:{newTab:"(在新分頁中開啟)"},spoiler:{reveal:"顯示內容",hide:"隱藏",notice:"此內容可能包含劇透"},chat:{sending:"傳送中",sent:"已傳送",delivered:"已送達",read:"已讀",failed:"傳送失敗",typing:"正在輸入…"},color:{area:"飽和度與明度",hue:"色相",alpha:"不透明度",value:"顏色值",swatches:"預設顏色",clear:"清除",empty:"選擇顏色"}},es:{link:{newTab:"(se abre en una pestaña nueva)"},spoiler:{reveal:"Mostrar",hide:"Ocultar",notice:"Puede contener spoilers"},chat:{sending:"Enviando",sent:"Enviado",delivered:"Entregado",read:"Leído",failed:"No enviado",typing:"Escribiendo…"},color:{area:"Saturación y brillo",hue:"Tono",alpha:"Opacidad",value:"Valor del color",swatches:"Colores predefinidos",clear:"Borrar",empty:"Elegir un color"}},pt:{link:{newTab:"(abre em uma nova aba)"},spoiler:{reveal:"Mostrar",hide:"Ocultar",notice:"Pode conter spoilers"},chat:{sending:"Enviando",sent:"Enviado",delivered:"Entregue",read:"Lido",failed:"Não enviado",typing:"Digitando…"},color:{area:"Saturação e brilho",hue:"Matiz",alpha:"Opacidade",value:"Valor da cor",swatches:"Cores predefinidas",clear:"Limpar",empty:"Escolher uma cor"}},fr:{link:{newTab:"(s’ouvre dans un nouvel onglet)"},spoiler:{reveal:"Afficher",hide:"Masquer",notice:"Peut contenir des spoilers"},chat:{sending:"Envoi en cours",sent:"Envoyé",delivered:"Distribué",read:"Lu",failed:"Non envoyé",typing:"En train d’écrire…"},color:{area:"Saturation et luminosité",hue:"Teinte",alpha:"Opacité",value:"Valeur de la couleur",swatches:"Couleurs prédéfinies",clear:"Effacer",empty:"Choisir une couleur"}},de:{link:{newTab:"(wird in einem neuen Tab geöffnet)"},spoiler:{reveal:"Anzeigen",hide:"Ausblenden",notice:"Kann Spoiler enthalten"},chat:{sending:"Wird gesendet",sent:"Gesendet",delivered:"Zugestellt",read:"Gelesen",failed:"Nicht gesendet",typing:"Schreibt…"},color:{area:"Sättigung und Helligkeit",hue:"Farbton",alpha:"Deckkraft",value:"Farbwert",swatches:"Vorgegebene Farben",clear:"Löschen",empty:"Farbe auswählen"}},it:{link:{newTab:"(si apre in una nuova scheda)"},spoiler:{reveal:"Mostra",hide:"Nascondi",notice:"Può contenere spoiler"},chat:{sending:"Invio in corso",sent:"Inviato",delivered:"Consegnato",read:"Letto",failed:"Non inviato",typing:"Sta scrivendo…"},color:{area:"Saturazione e luminosità",hue:"Tonalità",alpha:"Opacità",value:"Valore del colore",swatches:"Colori predefiniti",clear:"Cancella",empty:"Scegli un colore"}},nl:{link:{newTab:"(opent in een nieuw tabblad)"},spoiler:{reveal:"Tonen",hide:"Verbergen",notice:"Kan spoilers bevatten"},chat:{sending:"Wordt verzonden",sent:"Verzonden",delivered:"Afgeleverd",read:"Gelezen",failed:"Niet verzonden",typing:"Aan het typen…"},color:{area:"Verzadiging en helderheid",hue:"Kleurtoon",alpha:"Dekking",value:"Kleurwaarde",swatches:"Vooraf ingestelde kleuren",clear:"Wissen",empty:"Kies een kleur"}},pl:{link:{newTab:"(otwiera się w nowej karcie)"},spoiler:{reveal:"Pokaż",hide:"Ukryj",notice:"Może zawierać spoilery"},chat:{sending:"Wysyłanie",sent:"Wysłano",delivered:"Dostarczono",read:"Przeczytano",failed:"Nie wysłano",typing:"Pisze…"},color:{area:"Nasycenie i jasność",hue:"Barwa",alpha:"Krycie",value:"Wartość koloru",swatches:"Kolory predefiniowane",clear:"Wyczyść",empty:"Wybierz kolor"}},ru:{link:{newTab:"(откроется в новой вкладке)"},spoiler:{reveal:"Показать",hide:"Скрыть",notice:"Может содержать спойлеры"},chat:{sending:"Отправляется",sent:"Отправлено",delivered:"Доставлено",read:"Прочитано",failed:"Не отправлено",typing:"Печатает…"},color:{area:"Насыщенность и яркость",hue:"Оттенок",alpha:"Непрозрачность",value:"Значение цвета",swatches:"Готовые цвета",clear:"Очистить",empty:"Выберите цвет"}},tr:{link:{newTab:"(yeni sekmede açılır)"},spoiler:{reveal:"Göster",hide:"Gizle",notice:"Spoiler içerebilir"},chat:{sending:"Gönderiliyor",sent:"Gönderildi",delivered:"İletildi",read:"Okundu",failed:"Gönderilemedi",typing:"Yazıyor…"},color:{area:"Doygunluk ve parlaklık",hue:"Renk tonu",alpha:"Opaklık",value:"Renk değeri",swatches:"Hazır renkler",clear:"Temizle",empty:"Bir renk seçin"}},ar:{link:{newTab:"(يفتح في علامة تبويب جديدة)"},spoiler:{reveal:"إظهار",hide:"إخفاء",notice:"قد يحتوي على حرق للأحداث"},chat:{sending:"جارٍ الإرسال",sent:"تم الإرسال",delivered:"تم التسليم",read:"تمت القراءة",failed:"لم يتم الإرسال",typing:"يكتب الآن…"},color:{area:"التشبع والسطوع",hue:"درجة اللون",alpha:"العتامة",value:"قيمة اللون",swatches:"ألوان جاهزة",clear:"مسح",empty:"اختر لونًا"}},hi:{link:{newTab:"(नए टैब में खुलता है)"},spoiler:{reveal:"दिखाएँ",hide:"छिपाएँ",notice:"इसमें स्पॉइलर हो सकते हैं"},chat:{sending:"भेजा जा रहा है",sent:"भेजा गया",delivered:"डिलीवर हुआ",read:"पढ़ा गया",failed:"नहीं भेजा गया",typing:"टाइप कर रहे हैं…"},color:{area:"संतृप्ति और चमक",hue:"रंग",alpha:"अपारदर्शिता",value:"रंग मान",swatches:"पूर्व निर्धारित रंग",clear:"साफ़ करें",empty:"एक रंग चुनें"}},id:{link:{newTab:"(terbuka di tab baru)"},spoiler:{reveal:"Tampilkan",hide:"Sembunyikan",notice:"Mungkin mengandung spoiler"},chat:{sending:"Mengirim",sent:"Terkirim",delivered:"Diterima",read:"Dibaca",failed:"Gagal terkirim",typing:"Sedang mengetik…"},color:{area:"Saturasi dan kecerahan",hue:"Rona",alpha:"Opasitas",value:"Nilai warna",swatches:"Warna preset",clear:"Hapus",empty:"Pilih warna"}},vi:{link:{newTab:"(mở trong tab mới)"},spoiler:{reveal:"Hiện nội dung",hide:"Ẩn",notice:"Có thể chứa nội dung tiết lộ"},chat:{sending:"Đang gửi",sent:"Đã gửi",delivered:"Đã nhận",read:"Đã xem",failed:"Chưa gửi được",typing:"Đang nhập…"},color:{area:"Độ bão hòa và độ sáng",hue:"Sắc độ",alpha:"Độ mờ đục",value:"Giá trị màu",swatches:"Màu dựng sẵn",clear:"Xóa",empty:"Chọn màu"}},th:{link:{newTab:"(เปิดในแท็บใหม่)"},spoiler:{reveal:"แสดงเนื้อหา",hide:"ซ่อน",notice:"อาจมีการเปิดเผยเนื้อหา"},chat:{sending:"กำลังส่ง",sent:"ส่งแล้ว",delivered:"ส่งถึงแล้ว",read:"อ่านแล้ว",failed:"ส่งไม่สำเร็จ",typing:"กำลังพิมพ์…"},color:{area:"ความอิ่มตัวและความสว่าง",hue:"เฉดสี",alpha:"ความทึบ",value:"ค่าสี",swatches:"สีที่กำหนดไว้",clear:"ล้าง",empty:"เลือกสี"}}},i={zh:"zh-hans","zh-cn":"zh-hans","zh-my":"zh-hans","zh-sg":"zh-hans","zh-hk":"zh-hant","zh-mo":"zh-hant","zh-tw":"zh-hant"};const r=new Map([["",a]]);export function resolveMessages(e){const l=e?.trim()??"",t=r.get(l);if(t)return t;const o=function(e){const a=e.toLowerCase().split(/[-_]/).filter(Boolean),n=a[0];if(!n)return[];const i=a.slice(1),r=i.find(e=>/^[a-z]{4}$/.test(e)),l=i.find(e=>/^([a-z]{2}|\d{3})$/.test(e));return[r?`${n}-${r}`:"",l?`${n}-${l}`:"",n].filter(Boolean)}(l).map(e=>n[e]??n[i[e]??""]).find(Boolean),s=o?{link:{...a.link,...o.link},spoiler:{...a.spoiler,...o.spoiler},chat:{...a.chat,...o.chat},color:{...a.color,...o.color}}:a;return r.set(l,s),s}export function useMessages(a){return e.useMemo(()=>resolveMessages(a),[a])}
|
|
1
|
+
import*as e from"react";const a={link:{newTab:"(opens in a new tab)"},spoiler:{reveal:"Reveal",hide:"Hide",notice:"This may contain spoilers"},chat:{sending:"Sending",sent:"Sent",delivered:"Delivered",read:"Read",failed:"Not sent",typing:"Typing…"},empty:{title:"Nothing here"},table:{search:"Search",selectAll:"Select all rows",selectRow:"Select row",rowsPerPage:"Rows per page",range:"{start}–{end} of {total}",selected:"{count} selected"},color:{area:"Saturation and brightness",hue:"Hue",alpha:"Opacity",value:"Colour value",swatches:"Preset colours",clear:"Clear",empty:"Choose a colour"}},t={ko:{link:{newTab:"(새 창에서 열림)"},spoiler:{reveal:"내용 보기",hide:"숨기기",notice:"스포일러가 포함되어 있을 수 있습니다"},chat:{sending:"보내는 중",sent:"보냄",delivered:"전달됨",read:"읽음",failed:"전송 실패",typing:"입력 중…"},empty:{title:"내용이 없습니다"},table:{search:"검색",selectAll:"모든 행 선택",selectRow:"행 선택",rowsPerPage:"페이지당 행 수",range:"전체 {total}개 중 {start}–{end}",selected:"{count}개 선택됨"},color:{area:"채도와 명도",hue:"색상",alpha:"불투명도",value:"색상 값",swatches:"기본 색상",clear:"지우기",empty:"색상 선택"}},ja:{link:{newTab:"(新しいタブで開きます)"},spoiler:{reveal:"表示する",hide:"隠す",notice:"ネタバレを含む可能性があります"},chat:{sending:"送信中",sent:"送信済み",delivered:"配信済み",read:"既読",failed:"送信できませんでした",typing:"入力中…"},empty:{title:"表示するものがありません"},table:{search:"検索",selectAll:"すべての行を選択",selectRow:"行を選択",rowsPerPage:"1 ページの行数",range:"{total} 件中 {start}–{end} 件",selected:"{count} 件を選択中"},color:{area:"彩度と明度",hue:"色相",alpha:"不透明度",value:"カラー値",swatches:"プリセットの色",clear:"クリア",empty:"色を選択"}},"zh-hans":{link:{newTab:"(在新标签页中打开)"},spoiler:{reveal:"显示内容",hide:"隐藏",notice:"此内容可能包含剧透"},chat:{sending:"发送中",sent:"已发送",delivered:"已送达",read:"已读",failed:"发送失败",typing:"正在输入…"},empty:{title:"暂无内容"},table:{search:"搜索",selectAll:"全选所有行",selectRow:"选择此行",rowsPerPage:"每页行数",range:"第 {start}–{end} 行,共 {total} 行",selected:"已选择 {count} 行"},color:{area:"饱和度和明度",hue:"色相",alpha:"不透明度",value:"颜色值",swatches:"预设颜色",clear:"清除",empty:"选择颜色"}},"zh-hant":{link:{newTab:"(在新分頁中開啟)"},spoiler:{reveal:"顯示內容",hide:"隱藏",notice:"此內容可能包含劇透"},chat:{sending:"傳送中",sent:"已傳送",delivered:"已送達",read:"已讀",failed:"傳送失敗",typing:"正在輸入…"},empty:{title:"沒有內容"},table:{search:"搜尋",selectAll:"全選所有列",selectRow:"選擇此列",rowsPerPage:"每頁列數",range:"第 {start}–{end} 列,共 {total} 列",selected:"已選擇 {count} 列"},color:{area:"飽和度與明度",hue:"色相",alpha:"不透明度",value:"顏色值",swatches:"預設顏色",clear:"清除",empty:"選擇顏色"}},es:{link:{newTab:"(se abre en una pestaña nueva)"},spoiler:{reveal:"Mostrar",hide:"Ocultar",notice:"Puede contener spoilers"},chat:{sending:"Enviando",sent:"Enviado",delivered:"Entregado",read:"Leído",failed:"No enviado",typing:"Escribiendo…"},empty:{title:"No hay nada aquí"},table:{search:"Buscar",selectAll:"Seleccionar todas las filas",selectRow:"Seleccionar fila",rowsPerPage:"Filas por página",range:"{start}–{end} de {total}",selected:"{count} seleccionadas"},color:{area:"Saturación y brillo",hue:"Tono",alpha:"Opacidad",value:"Valor del color",swatches:"Colores predefinidos",clear:"Borrar",empty:"Elegir un color"}},pt:{link:{newTab:"(abre em uma nova aba)"},spoiler:{reveal:"Mostrar",hide:"Ocultar",notice:"Pode conter spoilers"},chat:{sending:"Enviando",sent:"Enviado",delivered:"Entregue",read:"Lido",failed:"Não enviado",typing:"Digitando…"},empty:{title:"Nada por aqui"},table:{search:"Pesquisar",selectAll:"Selecionar todas as linhas",selectRow:"Selecionar linha",rowsPerPage:"Linhas por página",range:"{start}–{end} de {total}",selected:"{count} selecionadas"},color:{area:"Saturação e brilho",hue:"Matiz",alpha:"Opacidade",value:"Valor da cor",swatches:"Cores predefinidas",clear:"Limpar",empty:"Escolher uma cor"}},fr:{link:{newTab:"(s’ouvre dans un nouvel onglet)"},spoiler:{reveal:"Afficher",hide:"Masquer",notice:"Peut contenir des spoilers"},chat:{sending:"Envoi en cours",sent:"Envoyé",delivered:"Distribué",read:"Lu",failed:"Non envoyé",typing:"En train d’écrire…"},empty:{title:"Rien ici"},table:{search:"Rechercher",selectAll:"Sélectionner toutes les lignes",selectRow:"Sélectionner la ligne",rowsPerPage:"Lignes par page",range:"{start}–{end} sur {total}",selected:"{count} sélectionnées"},color:{area:"Saturation et luminosité",hue:"Teinte",alpha:"Opacité",value:"Valeur de la couleur",swatches:"Couleurs prédéfinies",clear:"Effacer",empty:"Choisir une couleur"}},de:{link:{newTab:"(wird in einem neuen Tab geöffnet)"},spoiler:{reveal:"Anzeigen",hide:"Ausblenden",notice:"Kann Spoiler enthalten"},chat:{sending:"Wird gesendet",sent:"Gesendet",delivered:"Zugestellt",read:"Gelesen",failed:"Nicht gesendet",typing:"Schreibt…"},empty:{title:"Nichts vorhanden"},table:{search:"Suchen",selectAll:"Alle Zeilen auswählen",selectRow:"Zeile auswählen",rowsPerPage:"Zeilen pro Seite",range:"{start}–{end} von {total}",selected:"{count} ausgewählt"},color:{area:"Sättigung und Helligkeit",hue:"Farbton",alpha:"Deckkraft",value:"Farbwert",swatches:"Vorgegebene Farben",clear:"Löschen",empty:"Farbe auswählen"}},it:{link:{newTab:"(si apre in una nuova scheda)"},spoiler:{reveal:"Mostra",hide:"Nascondi",notice:"Può contenere spoiler"},chat:{sending:"Invio in corso",sent:"Inviato",delivered:"Consegnato",read:"Letto",failed:"Non inviato",typing:"Sta scrivendo…"},empty:{title:"Non c’è nulla"},table:{search:"Cerca",selectAll:"Seleziona tutte le righe",selectRow:"Seleziona riga",rowsPerPage:"Righe per pagina",range:"{start}–{end} di {total}",selected:"{count} selezionate"},color:{area:"Saturazione e luminosità",hue:"Tonalità",alpha:"Opacità",value:"Valore del colore",swatches:"Colori predefiniti",clear:"Cancella",empty:"Scegli un colore"}},nl:{link:{newTab:"(opent in een nieuw tabblad)"},spoiler:{reveal:"Tonen",hide:"Verbergen",notice:"Kan spoilers bevatten"},chat:{sending:"Wordt verzonden",sent:"Verzonden",delivered:"Afgeleverd",read:"Gelezen",failed:"Niet verzonden",typing:"Aan het typen…"},empty:{title:"Hier is niets"},table:{search:"Zoeken",selectAll:"Alle rijen selecteren",selectRow:"Rij selecteren",rowsPerPage:"Rijen per pagina",range:"{start}–{end} van {total}",selected:"{count} geselecteerd"},color:{area:"Verzadiging en helderheid",hue:"Kleurtoon",alpha:"Dekking",value:"Kleurwaarde",swatches:"Vooraf ingestelde kleuren",clear:"Wissen",empty:"Kies een kleur"}},pl:{link:{newTab:"(otwiera się w nowej karcie)"},spoiler:{reveal:"Pokaż",hide:"Ukryj",notice:"Może zawierać spoilery"},chat:{sending:"Wysyłanie",sent:"Wysłano",delivered:"Dostarczono",read:"Przeczytano",failed:"Nie wysłano",typing:"Pisze…"},empty:{title:"Nic tu nie ma"},table:{search:"Szukaj",selectAll:"Zaznacz wszystkie wiersze",selectRow:"Zaznacz wiersz",rowsPerPage:"Wierszy na stronę",range:"{start}–{end} z {total}",selected:"Zaznaczono: {count}"},color:{area:"Nasycenie i jasność",hue:"Barwa",alpha:"Krycie",value:"Wartość koloru",swatches:"Kolory predefiniowane",clear:"Wyczyść",empty:"Wybierz kolor"}},ru:{link:{newTab:"(откроется в новой вкладке)"},spoiler:{reveal:"Показать",hide:"Скрыть",notice:"Может содержать спойлеры"},chat:{sending:"Отправляется",sent:"Отправлено",delivered:"Доставлено",read:"Прочитано",failed:"Не отправлено",typing:"Печатает…"},empty:{title:"Здесь пусто"},table:{search:"Поиск",selectAll:"Выбрать все строки",selectRow:"Выбрать строку",rowsPerPage:"Строк на странице",range:"{start}–{end} из {total}",selected:"Выбрано: {count}"},color:{area:"Насыщенность и яркость",hue:"Оттенок",alpha:"Непрозрачность",value:"Значение цвета",swatches:"Готовые цвета",clear:"Очистить",empty:"Выберите цвет"}},tr:{link:{newTab:"(yeni sekmede açılır)"},spoiler:{reveal:"Göster",hide:"Gizle",notice:"Spoiler içerebilir"},chat:{sending:"Gönderiliyor",sent:"Gönderildi",delivered:"İletildi",read:"Okundu",failed:"Gönderilemedi",typing:"Yazıyor…"},empty:{title:"Burada bir şey yok"},table:{search:"Ara",selectAll:"Tüm satırları seç",selectRow:"Satırı seç",rowsPerPage:"Sayfa başına satır",range:"{total} kayıttan {start}–{end}",selected:"{count} seçildi"},color:{area:"Doygunluk ve parlaklık",hue:"Renk tonu",alpha:"Opaklık",value:"Renk değeri",swatches:"Hazır renkler",clear:"Temizle",empty:"Bir renk seçin"}},ar:{link:{newTab:"(يفتح في علامة تبويب جديدة)"},spoiler:{reveal:"إظهار",hide:"إخفاء",notice:"قد يحتوي على حرق للأحداث"},chat:{sending:"جارٍ الإرسال",sent:"تم الإرسال",delivered:"تم التسليم",read:"تمت القراءة",failed:"لم يتم الإرسال",typing:"يكتب الآن…"},empty:{title:"لا يوجد شيء هنا"},table:{search:"بحث",selectAll:"تحديد كل الصفوف",selectRow:"تحديد الصف",rowsPerPage:"صفوف لكل صفحة",range:"{start}–{end} من {total}",selected:"تم تحديد {count}"},color:{area:"التشبع والسطوع",hue:"درجة اللون",alpha:"العتامة",value:"قيمة اللون",swatches:"ألوان جاهزة",clear:"مسح",empty:"اختر لونًا"}},hi:{link:{newTab:"(नए टैब में खुलता है)"},spoiler:{reveal:"दिखाएँ",hide:"छिपाएँ",notice:"इसमें स्पॉइलर हो सकते हैं"},chat:{sending:"भेजा जा रहा है",sent:"भेजा गया",delivered:"डिलीवर हुआ",read:"पढ़ा गया",failed:"नहीं भेजा गया",typing:"टाइप कर रहे हैं…"},empty:{title:"यहाँ कुछ नहीं है"},table:{search:"खोजें",selectAll:"सभी पंक्तियाँ चुनें",selectRow:"पंक्ति चुनें",rowsPerPage:"प्रति पृष्ठ पंक्तियाँ",range:"{total} में से {start}–{end}",selected:"{count} चुनी गईं"},color:{area:"संतृप्ति और चमक",hue:"रंग",alpha:"अपारदर्शिता",value:"रंग मान",swatches:"पूर्व निर्धारित रंग",clear:"साफ़ करें",empty:"एक रंग चुनें"}},id:{link:{newTab:"(terbuka di tab baru)"},spoiler:{reveal:"Tampilkan",hide:"Sembunyikan",notice:"Mungkin mengandung spoiler"},chat:{sending:"Mengirim",sent:"Terkirim",delivered:"Diterima",read:"Dibaca",failed:"Gagal terkirim",typing:"Sedang mengetik…"},empty:{title:"Tidak ada apa-apa di sini"},table:{search:"Cari",selectAll:"Pilih semua baris",selectRow:"Pilih baris",rowsPerPage:"Baris per halaman",range:"{start}–{end} dari {total}",selected:"{count} dipilih"},color:{area:"Saturasi dan kecerahan",hue:"Rona",alpha:"Opasitas",value:"Nilai warna",swatches:"Warna preset",clear:"Hapus",empty:"Pilih warna"}},vi:{link:{newTab:"(mở trong tab mới)"},spoiler:{reveal:"Hiện nội dung",hide:"Ẩn",notice:"Có thể chứa nội dung tiết lộ"},chat:{sending:"Đang gửi",sent:"Đã gửi",delivered:"Đã nhận",read:"Đã xem",failed:"Chưa gửi được",typing:"Đang nhập…"},empty:{title:"Không có gì ở đây"},table:{search:"Tìm kiếm",selectAll:"Chọn tất cả các hàng",selectRow:"Chọn hàng",rowsPerPage:"Số hàng mỗi trang",range:"{start}–{end} trên {total}",selected:"Đã chọn {count}"},color:{area:"Độ bão hòa và độ sáng",hue:"Sắc độ",alpha:"Độ mờ đục",value:"Giá trị màu",swatches:"Màu dựng sẵn",clear:"Xóa",empty:"Chọn màu"}},th:{link:{newTab:"(เปิดในแท็บใหม่)"},spoiler:{reveal:"แสดงเนื้อหา",hide:"ซ่อน",notice:"อาจมีการเปิดเผยเนื้อหา"},chat:{sending:"กำลังส่ง",sent:"ส่งแล้ว",delivered:"ส่งถึงแล้ว",read:"อ่านแล้ว",failed:"ส่งไม่สำเร็จ",typing:"กำลังพิมพ์…"},empty:{title:"ไม่มีอะไรที่นี่"},table:{search:"ค้นหา",selectAll:"เลือกทุกแถว",selectRow:"เลือกแถวนี้",rowsPerPage:"จำนวนแถวต่อหน้า",range:"{start}–{end} จาก {total}",selected:"เลือกแล้ว {count} รายการ"},color:{area:"ความอิ่มตัวและความสว่าง",hue:"เฉดสี",alpha:"ความทึบ",value:"ค่าสี",swatches:"สีที่กำหนดไว้",clear:"ล้าง",empty:"เลือกสี"}}},l={zh:"zh-hans","zh-cn":"zh-hans","zh-my":"zh-hans","zh-sg":"zh-hans","zh-hk":"zh-hant","zh-mo":"zh-hant","zh-tw":"zh-hant"};const n=new Map([["",a]]);export function resolveMessages(e){const r=e?.trim()??"",i=n.get(r);if(i)return i;const s=function(e){const a=e.toLowerCase().split(/[-_]/).filter(Boolean),t=a[0];if(!t)return[];const l=a.slice(1),n=l.find(e=>/^[a-z]{4}$/.test(e)),r=l.find(e=>/^([a-z]{2}|\d{3})$/.test(e));return[n?`${t}-${n}`:"",r?`${t}-${r}`:"",t].filter(Boolean)}(r).map(e=>t[e]??t[l[e]??""]).find(Boolean),o=s?{link:{...a.link,...s.link},spoiler:{...a.spoiler,...s.spoiler},chat:{...a.chat,...s.chat},empty:{...a.empty,...s.empty},table:{...a.table,...s.table},color:{...a.color,...s.color}}:a;return n.set(r,o),o}export function useMessages(a){return e.useMemo(()=>resolveMessages(a),[a])}export function fillMessage(e,a){return e.replace(/\{(\w+)\}/g,(e,t)=>a[t]??e)}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The device a Mockup is a picture of: the tables that say how big it is, and
|
|
3
|
+
* the drawings that go on its screen.
|
|
4
|
+
*
|
|
5
|
+
* It lives here for the reason `internal/color.ts` does. Only one component
|
|
6
|
+
* reads it, but what it holds is a body of reference data rather than a piece of
|
|
7
|
+
* that component — five resolutions per device, three shells, six systems' worth
|
|
8
|
+
* of chrome — and a component file with all of that in it would be a table with
|
|
9
|
+
* a `forwardRef` at the bottom.
|
|
10
|
+
*
|
|
11
|
+
* Two conventions run through the whole file:
|
|
12
|
+
*
|
|
13
|
+
* **Every length in here is a device pixel.** The screen is laid out at the
|
|
14
|
+
* resolution it claims to have and the whole frame is scaled once, at the top,
|
|
15
|
+
* so a 54px status bar is 54px on the phone rather than 54px on the page. That
|
|
16
|
+
* is also why the geometry is written as inline styles rather than as utilities:
|
|
17
|
+
* these are numbers off a table, computed per render, and Tailwind only ever
|
|
18
|
+
* sees class names that appear literally in the source. Utilities are still what
|
|
19
|
+
* does the layout — the inline styles are only ever the measurements.
|
|
20
|
+
*
|
|
21
|
+
* **The chrome draws no words except the clock.** A menu bar's titles, a dock's
|
|
22
|
+
* icons and a status bar's carrier are abstract shapes, which is what keeps this
|
|
23
|
+
* an impression of a system rather than a copy of one: nothing to translate,
|
|
24
|
+
* nothing to redraw when a version ships, and no other party's marks in the
|
|
25
|
+
* library. The clock is the exception because a blank rectangle where the time
|
|
26
|
+
* goes reads as a bug, and it is a prop.
|
|
27
|
+
*/
|
|
28
|
+
import * as React from 'react';
|
|
29
|
+
import type { NebaSize } from '../types';
|
|
30
|
+
/** Which machine the mockup is a picture of. */
|
|
31
|
+
export type NebaMockupDevice = 'desktop' | 'tablet' | 'mobile';
|
|
32
|
+
/**
|
|
33
|
+
* The system whose chrome is drawn on the screen.
|
|
34
|
+
*
|
|
35
|
+
* One union across all three devices rather than one per device: a caller
|
|
36
|
+
* reading the type should see the whole set, and a device offered an OS that is
|
|
37
|
+
* not its own falls back to its default rather than failing to compile — which
|
|
38
|
+
* is the behaviour a single `Mockup` with a `device` prop has to have anyway.
|
|
39
|
+
*/
|
|
40
|
+
export type NebaMockupOs = 'macos' | 'windows' | 'linux' | 'ios' | 'ipados' | 'android';
|
|
41
|
+
/** What the hardware around a desktop screen is. */
|
|
42
|
+
export type NebaMockupHardware = 'monitor' | 'laptop';
|
|
43
|
+
/**
|
|
44
|
+
* The camera cut-out at the top of a screen.
|
|
45
|
+
*
|
|
46
|
+
* Hardware, not chrome — it is drawn whether or not `systemUi` is on, because a
|
|
47
|
+
* phone with the status bar hidden still has a hole in its screen.
|
|
48
|
+
*/
|
|
49
|
+
export type NebaMockupNotch = 'none' | 'notch' | 'dynamic-island' | 'punch-hole';
|
|
50
|
+
/**
|
|
51
|
+
* How much hardware there is around the screen.
|
|
52
|
+
*
|
|
53
|
+
* `none` is not a thinner bezel — it is no hardware at all: no frame, no stand,
|
|
54
|
+
* no laptop base, just the screen with its corners cut. It is what a mockup that
|
|
55
|
+
* only wants to say "this is a phone-shaped viewport" asks for.
|
|
56
|
+
*
|
|
57
|
+
* `thick` is an older device rather than a wider version of `standard`: the
|
|
58
|
+
* sides stay narrow and the forehead and chin grow, which is where a bezel
|
|
59
|
+
* actually goes when there is a lot of it.
|
|
60
|
+
*/
|
|
61
|
+
export type NebaMockupBezel = 'none' | 'thin' | 'standard' | 'thick';
|
|
62
|
+
/** What the hardware is made of. */
|
|
63
|
+
export type NebaMockupFinish = 'graphite' | 'silver' | 'white';
|
|
64
|
+
/**
|
|
65
|
+
* Which way a handheld is held.
|
|
66
|
+
*
|
|
67
|
+
* `portrait`/`landscape` rather than `NebaOrientation`'s `vertical`/`horizontal`,
|
|
68
|
+
* and this is the one place the library spells the idea twice on purpose. A
|
|
69
|
+
* Divider running horizontally is not "landscape", and a device held upright is
|
|
70
|
+
* not "vertical" in any vocabulary a designer or a media query uses. CSS itself
|
|
71
|
+
* keeps both pairs for exactly this reason.
|
|
72
|
+
*/
|
|
73
|
+
export type NebaMockupOrientation = 'portrait' | 'landscape';
|
|
74
|
+
/** A screen's logical resolution, in CSS pixels. */
|
|
75
|
+
export interface NebaMockupResolution {
|
|
76
|
+
width: number;
|
|
77
|
+
height: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* The system a device will actually draw.
|
|
81
|
+
*
|
|
82
|
+
* An OS the device does not run falls back to its default, with one nicety: a
|
|
83
|
+
* caller who writes `ios` on a tablet or `ipados` on a phone meant the Apple one
|
|
84
|
+
* and gets it, rather than being sent back to the start of the list.
|
|
85
|
+
*/
|
|
86
|
+
export declare function resolveOs(device: NebaMockupDevice, os?: NebaMockupOs): NebaMockupOs;
|
|
87
|
+
/** What a device puts in its screen when the caller says nothing. */
|
|
88
|
+
export declare function defaultNotch(device: NebaMockupDevice, os: NebaMockupOs): NebaMockupNotch;
|
|
89
|
+
export declare const resolutions: Record<NebaMockupDevice, Record<NebaSize, NebaMockupResolution>>;
|
|
90
|
+
/** How much hardware sits on each side of the screen. */
|
|
91
|
+
export interface MockupInset {
|
|
92
|
+
x: number;
|
|
93
|
+
top: number;
|
|
94
|
+
bottom: number;
|
|
95
|
+
}
|
|
96
|
+
/** Every number the component needs to lay a device out, in device pixels. */
|
|
97
|
+
export interface MockupMetrics {
|
|
98
|
+
/** The screen, after `orientation` has had its say. */
|
|
99
|
+
screen: NebaMockupResolution;
|
|
100
|
+
/** The hardware around it. Zero on all four sides when `bezel` is `none`. */
|
|
101
|
+
bezel: MockupInset;
|
|
102
|
+
/** Screen plus bezel: the part you would call the device's face. */
|
|
103
|
+
body: {
|
|
104
|
+
width: number;
|
|
105
|
+
height: number;
|
|
106
|
+
};
|
|
107
|
+
/** Face plus whatever holds it up. This is what gets scaled to fit. */
|
|
108
|
+
frame: {
|
|
109
|
+
width: number;
|
|
110
|
+
height: number;
|
|
111
|
+
};
|
|
112
|
+
frameRadius: number;
|
|
113
|
+
screenRadius: number;
|
|
114
|
+
/** A monitor's neck and foot, when there is one. */
|
|
115
|
+
stand: {
|
|
116
|
+
neckWidth: number;
|
|
117
|
+
neckHeight: number;
|
|
118
|
+
footWidth: number;
|
|
119
|
+
footHeight: number;
|
|
120
|
+
} | null;
|
|
121
|
+
/** A laptop's base, when there is one. */
|
|
122
|
+
base: {
|
|
123
|
+
width: number;
|
|
124
|
+
height: number;
|
|
125
|
+
lipWidth: number;
|
|
126
|
+
} | null;
|
|
127
|
+
}
|
|
128
|
+
export declare function mockupMetrics(options: {
|
|
129
|
+
device: NebaMockupDevice;
|
|
130
|
+
size: NebaSize;
|
|
131
|
+
resolution?: NebaMockupResolution;
|
|
132
|
+
orientation: NebaMockupOrientation;
|
|
133
|
+
bezel: NebaMockupBezel;
|
|
134
|
+
hardware: NebaMockupHardware;
|
|
135
|
+
}): MockupMetrics;
|
|
136
|
+
export declare const finishSlots: Record<NebaMockupFinish, React.CSSProperties>;
|
|
137
|
+
/**
|
|
138
|
+
* The hardware's surface: the finish, a light top edge and a hairline all the
|
|
139
|
+
* way round, which is the plate the design language puts on everything else. No
|
|
140
|
+
* dark bevel underneath — the shade is a ring, not a shadow.
|
|
141
|
+
*/
|
|
142
|
+
export declare const shellClasses = "bg-(--n-shell) [box-shadow:inset_0_1px_0_var(--n-shell-edge),inset_0_0_0_1px_var(--n-shell-shade)]";
|
|
143
|
+
/** How far off the page the whole device sits, as a silhouette rather than a box.
|
|
144
|
+
*
|
|
145
|
+
* `drop-shadow` rather than `box-shadow` for one reason: the shadow has to
|
|
146
|
+
* follow a rounded lid on a narrow neck on a wide foot, and a box-shadow would
|
|
147
|
+
* draw the rectangle that contains all three. It also sits outside the scale,
|
|
148
|
+
* so a device shrunk to a third of its size does not get a third of its shadow.
|
|
149
|
+
*/
|
|
150
|
+
export declare const elevationFilters: readonly ["none", "drop-shadow(0 1px 2px var(--neba-shadow-ambient))", "drop-shadow(0 2px 4px var(--neba-shadow-ambient)) drop-shadow(0 8px 12px var(--neba-shadow-ambient))", "drop-shadow(0 4px 6px var(--neba-shadow-ambient)) drop-shadow(0 18px 28px var(--neba-shadow-ambient))"];
|
|
151
|
+
/**
|
|
152
|
+
* The camera, drawn on the glass.
|
|
153
|
+
*
|
|
154
|
+
* Portrait puts it against the top edge and landscape against the leading one,
|
|
155
|
+
* which is where it goes on a real device turned the same way — and it is why
|
|
156
|
+
* the island does not collide with the status bar in landscape: it has moved out
|
|
157
|
+
* from under it.
|
|
158
|
+
*/
|
|
159
|
+
export declare function MockupCutout({ notch, screen, landscape }: {
|
|
160
|
+
notch: NebaMockupNotch;
|
|
161
|
+
screen: NebaMockupResolution;
|
|
162
|
+
landscape: boolean;
|
|
163
|
+
}): React.JSX.Element | null;
|
|
164
|
+
/** What a system puts on the screen, and how much room it takes. */
|
|
165
|
+
export interface MockupChrome {
|
|
166
|
+
top?: {
|
|
167
|
+
size: number;
|
|
168
|
+
node: React.ReactNode;
|
|
169
|
+
};
|
|
170
|
+
bottom?: {
|
|
171
|
+
size: number;
|
|
172
|
+
node: React.ReactNode;
|
|
173
|
+
};
|
|
174
|
+
/** A dock down the leading edge. Only Linux has one. */
|
|
175
|
+
start?: {
|
|
176
|
+
size: number;
|
|
177
|
+
node: React.ReactNode;
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* The bars, per system.
|
|
182
|
+
*
|
|
183
|
+
* Each one takes its own space rather than floating over the content: a caller
|
|
184
|
+
* putting a screenshot in a mockup wants all of the screenshot, and a status bar
|
|
185
|
+
* that covered the top of it would be a crop nobody asked for. The cut-out is
|
|
186
|
+
* the exception, because that one really is a hole in the glass.
|
|
187
|
+
*/
|
|
188
|
+
export declare function mockupChrome(options: {
|
|
189
|
+
os: NebaMockupOs;
|
|
190
|
+
notch: NebaMockupNotch;
|
|
191
|
+
landscape: boolean;
|
|
192
|
+
time: string;
|
|
193
|
+
}): MockupChrome;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";const i={desktop:["macos","windows","linux"],tablet:["ipados","android"],mobile:["ios","android"]};export function resolveOs(e,t){const n=i[e];return t&&n.includes(t)?t:"ios"===t&&"tablet"===e?"ipados":"ipados"===t&&"mobile"===e?"ios":n[0]}export function defaultNotch(e,t){return"mobile"!==e?"none":"android"===t?"punch-hole":"dynamic-island"}export const resolutions={mobile:{xs:{width:320,height:568},sm:{width:360,height:780},md:{width:390,height:844},lg:{width:414,height:896},xl:{width:430,height:932}},tablet:{xs:{width:744,height:1133},sm:{width:768,height:1024},md:{width:820,height:1180},lg:{width:834,height:1194},xl:{width:1024,height:1366}},desktop:{xs:{width:1024,height:640},sm:{width:1280,height:800},md:{width:1440,height:900},lg:{width:1680,height:1050},xl:{width:1920,height:1200}}};const n={mobile:{thin:{bezel:{x:8,top:8,bottom:8},frameRadius:50,screenRadius:42},standard:{bezel:{x:13,top:13,bottom:13},frameRadius:56,screenRadius:43},thick:{bezel:{x:16,top:62,bottom:62},frameRadius:40,screenRadius:4}},tablet:{thin:{bezel:{x:12,top:12,bottom:12},frameRadius:34,screenRadius:22},standard:{bezel:{x:20,top:20,bottom:20},frameRadius:42,screenRadius:22},thick:{bezel:{x:28,top:74,bottom:74},frameRadius:36,screenRadius:4}},desktop:{thin:{bezel:{x:8,top:8,bottom:8},frameRadius:12,screenRadius:4},standard:{bezel:{x:13,top:13,bottom:30},frameRadius:16,screenRadius:4},thick:{bezel:{x:22,top:22,bottom:62},frameRadius:18,screenRadius:3}}},a={mobile:42,tablet:24,desktop:8};export function mockupMetrics(e){const{device:t,size:i,resolution:r,orientation:d,bezel:h,hardware:s}=e,o=r??resolutions[t][i],l="desktop"!==t&&"landscape"===d,c=l?{width:o.height,height:o.width}:o;if("none"===h)return{screen:c,bezel:{x:0,top:0,bottom:0},body:{...c},frame:{...c},frameRadius:a[t],screenRadius:a[t],stand:null,base:null};const u=n[t][h],g=l?{x:u.bezel.top,top:u.bezel.x,bottom:u.bezel.x}:u.bezel,p="desktop"===t&&"laptop"===s,m=p?{...g,bottom:g.top}:g,x={width:c.width+2*m.x,height:c.height+m.top+m.bottom};if("desktop"!==t)return{screen:c,bezel:m,body:x,frame:{...x},frameRadius:u.frameRadius,screenRadius:u.screenRadius,stand:null,base:null};if(p){const e={width:Math.round(1.075*x.width),height:Math.round(.035*x.height),lipWidth:Math.round(.12*x.width)};return{screen:c,bezel:m,body:x,frame:{width:e.width,height:x.height+e.height},frameRadius:u.frameRadius,screenRadius:u.screenRadius,stand:null,base:e}}const b={neckWidth:Math.round(.11*x.width),neckHeight:Math.round(.09*x.height),footWidth:Math.round(.28*x.width),footHeight:Math.round(.018*x.height)};return{screen:c,bezel:m,body:x,frame:{width:x.width,height:x.height+b.neckHeight+b.footHeight},frameRadius:u.frameRadius,screenRadius:u.screenRadius,stand:b,base:null}}export const finishSlots={graphite:{"--n-shell":"oklch(27% 0.008 262)","--n-shell-edge":"rgb(255 255 255 / 0.16)","--n-shell-shade":"oklch(17% 0.008 262)"},silver:{"--n-shell":"oklch(83% 0.004 262)","--n-shell-edge":"rgb(255 255 255 / 0.75)","--n-shell-shade":"oklch(66% 0.006 262)"},white:{"--n-shell":"oklch(96% 0.002 262)","--n-shell-edge":"rgb(255 255 255 / 0.9)","--n-shell-shade":"oklch(80% 0.004 262)"}};export const shellClasses="bg-(--n-shell) [box-shadow:inset_0_1px_0_var(--n-shell-edge),inset_0_0_0_1px_var(--n-shell-shade)]";export const elevationFilters=["none","drop-shadow(0 1px 2px var(--neba-shadow-ambient))","drop-shadow(0 2px 4px var(--neba-shadow-ambient)) drop-shadow(0 8px 12px var(--neba-shadow-ambient))","drop-shadow(0 4px 6px var(--neba-shadow-ambient)) drop-shadow(0 18px 28px var(--neba-shadow-ambient))"];export function MockupCutout({notch:t,screen:i,landscape:n}){if("none"===t)return null;const a=n?i.height:i.width,r={position:"absolute",background:"oklch(12% 0.006 262)",pointerEvents:"none",zIndex:20},d="neba-mockup-cutout";if("punch-hole"===t){const t=Math.max(16,Math.round(.07*a)),i=Math.round(.55*t);return e("div",{"aria-hidden":"true",className:d,style:{...r,width:t,height:t,borderRadius:"50%",...n?{left:i,top:"50%",marginTop:-t/2}:{top:i,left:"50%",marginLeft:-t/2}}})}if("dynamic-island"===t){const t=Math.max(96,Math.round(.32*a)),i=Math.round(.29*t),h=Math.round(.32*i);return e("div",{"aria-hidden":"true",className:d,style:{...r,borderRadius:i,...n?{left:h,top:"50%",width:i,height:t,marginTop:-t/2}:{top:h,left:"50%",width:t,height:i,marginLeft:-t/2}}})}const h=Math.max(120,Math.round(.42*a)),s=Math.round(.23*h),o=Math.round(.6*s);return e("div",{"aria-hidden":"true",className:d,style:{...r,...n?{left:0,top:"50%",width:s,height:h,marginTop:-h/2,borderRadius:`0 ${o}px ${o}px 0`}:{top:0,left:"50%",width:h,height:s,marginLeft:-h/2,borderRadius:`0 0 ${o}px ${o}px`}}})}const r="relative z-10 flex shrink-0 items-center [background:color-mix(in_oklab,var(--neba-surface)_88%,transparent)]",d="font-medium text-(--neba-fg) tabular-nums";function h({width:t,height:i,radius:n,tone:a="muted"}){return e("div",{style:{width:t,height:i??t,borderRadius:n,background:"accent"===a?"var(--n-accent)":"faint"===a?"color-mix(in oklab, var(--neba-fg) 12%, transparent)":"color-mix(in oklab, var(--neba-fg) 26%, transparent)"}})}function s({count:t,size:i,radius:n,gap:a,accent:r=!1}){return e("div",{className:"flex items-center",style:{gap:a},children:Array.from({length:t},(t,a)=>e(h,{width:i,radius:n,tone:r&&0===a?"accent":"muted"},a))})}function o({height:i}){return t("svg",{viewBox:"0 0 17 11",height:i,width:17*i/11,fill:"currentColor","aria-hidden":"true",children:[e("rect",{y:"7.5",width:"3",height:"3.5",rx:"1"}),e("rect",{x:"4.7",y:"5",width:"3",height:"6",rx:"1"}),e("rect",{x:"9.4",y:"2.5",width:"3",height:"8.5",rx:"1"}),e("rect",{x:"14",width:"3",height:"11",rx:"1",opacity:"0.35"})]})}function l({height:i}){return t("svg",{viewBox:"0 0 16 12",height:i,width:16*i/12,fill:"none","aria-hidden":"true",children:[e("path",{d:"M1 4.2a10.5 10.5 0 0 1 14 0",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round"}),e("path",{d:"M3.6 7a6.8 6.8 0 0 1 8.8 0",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round"}),e("circle",{cx:"8",cy:"10.2",r:"1.6",fill:"currentColor"})]})}function c({height:i}){return t("svg",{viewBox:"0 0 25 12",height:i,width:25*i/12,fill:"none","aria-hidden":"true",children:[e("rect",{x:"0.7",y:"0.7",width:"20.6",height:"10.6",rx:"3.2",stroke:"currentColor",strokeWidth:"1.3",opacity:"0.45"}),e("rect",{x:"2.6",y:"2.6",width:"12.8",height:"6.8",rx:"1.8",fill:"currentColor"}),e("rect",{x:"22.8",y:"4",width:"1.8",height:"4",rx:"0.9",fill:"currentColor",opacity:"0.45"})]})}function u({height:i,gap:n}){return t("div",{className:"flex items-center text-(--neba-fg)",style:{gap:n},children:[e(o,{height:i}),e(l,{height:i}),e(c,{height:i})]})}function g({size:i,gap:n}){return t("div",{className:"flex items-center justify-center text-(--neba-fg)",style:{gap:n,opacity:.72},children:[e("svg",{viewBox:"0 0 16 16",width:i,height:i,fill:"none","aria-hidden":"true",children:e("path",{d:"M10 3 5 8l5 5",stroke:"currentColor",strokeWidth:"1.6",strokeLinecap:"round",strokeLinejoin:"round"})}),e("svg",{viewBox:"0 0 16 16",width:i,height:i,fill:"none","aria-hidden":"true",children:e("circle",{cx:"8",cy:"8",r:"5",stroke:"currentColor",strokeWidth:"1.6"})}),e("svg",{viewBox:"0 0 16 16",width:i,height:i,fill:"none","aria-hidden":"true",children:e("rect",{x:"3.5",y:"3.5",width:"9",height:"9",rx:"1.6",stroke:"currentColor",strokeWidth:"1.6"})})]})}function p({size:i}){return t("svg",{viewBox:"0 0 16 16",width:i,height:i,fill:"currentColor","aria-hidden":"true",children:[e("rect",{x:"1",y:"1",width:"6",height:"6",rx:"1.4"}),e("rect",{x:"9",y:"1",width:"6",height:"6",rx:"1.4"}),e("rect",{x:"1",y:"9",width:"6",height:"6",rx:"1.4"}),e("rect",{x:"9",y:"9",width:"6",height:"6",rx:"1.4"})]})}export function mockupChrome(i){const{os:n,notch:a,landscape:o,time:l}=i;if("ios"===n||"ipados"===n){const i="ipados"===n,h=i?30:!i&&!o&&"none"!==a&&"punch-hole"!==a?54:44;return{top:{size:h,node:t("div",{"aria-hidden":"true",className:`${r} justify-between`,style:{height:h,paddingInline:i?22:26},children:[e("span",{className:`${d} text-[15px]`,children:l}),e(u,{height:i?11:12,gap:6})]})},bottom:{size:i?22:34,node:e("div",{"aria-hidden":"true",className:`${r} justify-center`,style:{height:i?22:34,background:"transparent"},children:e("div",{style:{width:i?220:140,height:5,borderRadius:3,background:"color-mix(in oklab, var(--neba-fg) 55%, transparent)"}})})}}}return"android"===n?{top:{size:34,node:t("div",{"aria-hidden":"true",className:`${r} justify-between`,style:{height:34,paddingInline:18},children:[e("span",{className:`${d} text-[13px]`,children:l}),e(u,{height:11,gap:5})]})},bottom:{size:48,node:e("div",{"aria-hidden":"true",className:`${r} justify-center`,style:{height:48},children:e(g,{size:20,gap:72})})}}:"macos"===n?{top:{size:28,node:t("div",{"aria-hidden":"true",className:`${r} justify-between`,style:{height:28,paddingInline:16},children:[t("div",{className:"flex items-center",style:{gap:16},children:[e(h,{width:13,radius:4}),e(h,{width:34,height:7,radius:4}),e(h,{width:26,height:7,radius:4,tone:"faint"}),e(h,{width:30,height:7,radius:4,tone:"faint"}),e(h,{width:22,height:7,radius:4,tone:"faint"})]}),t("div",{className:"flex items-center",style:{gap:14},children:[e(h,{width:11,radius:3,tone:"faint"}),e(h,{width:11,radius:3,tone:"faint"}),e("span",{className:`${d} text-[13px]`,children:l})]})]})},bottom:{size:78,node:e("div",{"aria-hidden":"true",className:"flex shrink-0 items-end justify-center",style:{height:78},children:t("div",{className:`${r} [box-shadow:var(--neba-shadow-2),var(--neba-plate-glass)]`,style:{gap:10,padding:8,marginBottom:10,borderRadius:22},children:[e(s,{count:5,size:52,radius:14,gap:10,accent:!0}),e("div",{style:{width:1,height:44,background:"color-mix(in oklab, var(--neba-fg) 16%, transparent)"}}),e(s,{count:2,size:52,radius:14,gap:10})]})})}}:"windows"===n?{bottom:{size:52,node:t("div",{"aria-hidden":"true",className:`${r} justify-center [border-block-start:1px_solid_var(--neba-border)]`,style:{height:52,paddingInline:16},children:[t("div",{className:"flex items-center",style:{gap:10},children:[e("div",{className:"text-(--neba-fg)",style:{opacity:.7},children:e(p,{size:22})}),e(s,{count:6,size:30,radius:8,gap:10,accent:!0})]}),t("div",{className:"absolute flex items-center",style:{insetInlineEnd:16,gap:12},children:[e(h,{width:11,radius:3,tone:"faint"}),e(h,{width:11,radius:3,tone:"faint"}),e("span",{className:`${d} text-[12px]`,children:l})]})]})}}:{top:{size:34,node:t("div",{"aria-hidden":"true",className:`${r} justify-center`,style:{height:34,paddingInline:14},children:[e("div",{className:"absolute",style:{insetInlineStart:14},children:e(h,{width:52,height:9,radius:5})}),e("span",{className:`${d} text-[13px]`,children:l}),t("div",{className:"absolute flex items-center",style:{insetInlineEnd:14,gap:10},children:[e(h,{width:10,radius:3,tone:"faint"}),e(h,{width:10,radius:3,tone:"faint"}),e(h,{width:10,radius:3,tone:"faint"})]})]})},start:{size:66,node:t("div",{"aria-hidden":"true",className:`${r} flex-col justify-start [border-inline-end:1px_solid_var(--neba-border)]`,style:{width:66,height:"100%",gap:10,paddingBlock:12},children:[e(h,{width:44,radius:12,tone:"accent"}),e(h,{width:44,radius:12}),e(h,{width:44,radius:12}),e(h,{width:44,radius:12})]})}}}
|