@payglocal_ui/flux-ui 0.3.0 → 0.3.2
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/index.cjs +456 -223
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -3
- package/dist/index.d.ts +62 -3
- package/dist/index.js +483 -250
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/__tests__/copyable-cell-tooltip.test.tsx +81 -0
- package/src/__tests__/data-table-column-width.test.tsx +77 -0
- package/src/__tests__/date-picker-show-time.test.tsx +189 -0
- package/src/__tests__/picker-in-dialog.test.tsx +140 -0
- package/src/copyable-cell.tsx +65 -26
- package/src/data-table.tsx +65 -9
- package/src/date-picker.tsx +459 -126
- package/src/index.ts +1 -1
- package/src/time-picker.tsx +95 -66
package/src/index.ts
CHANGED
|
@@ -278,7 +278,7 @@ export type { AvatarTagProps, AvatarTagSize } from "./avatar-tag";
|
|
|
278
278
|
export { Calendar, CalendarDayButton } from "./calendar";
|
|
279
279
|
export type { CalendarProps } from "./calendar";
|
|
280
280
|
export type { DateRange } from "react-day-picker";
|
|
281
|
-
export { DatePicker } from "./date-picker";
|
|
281
|
+
export { DatePicker, type DatePickerTimeOptions } from "./date-picker";
|
|
282
282
|
|
|
283
283
|
// Charts
|
|
284
284
|
export {
|
package/src/time-picker.tsx
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { createPortal } from "react-dom";
|
|
5
|
+
import { RemoveScroll } from "react-remove-scroll";
|
|
5
6
|
import { Clock, ChevronDown, X } from "lucide-react";
|
|
6
7
|
import { cn } from "./utils";
|
|
7
8
|
|
|
@@ -309,78 +310,106 @@ export const TimePicker = React.forwardRef<HTMLButtonElement, TimePickerProps>(
|
|
|
309
310
|
}
|
|
310
311
|
|
|
311
312
|
/* ── Panel ── */
|
|
313
|
+
/**
|
|
314
|
+
* Wrapped in `RemoveScroll` so the columns can be scrolled inside a modal
|
|
315
|
+
* Dialog or Drawer.
|
|
316
|
+
*
|
|
317
|
+
* Radix's Dialog renders its overlay inside `RemoveScroll` with only
|
|
318
|
+
* `Dialog.Content` as a shard. This panel is portaled to `document.body`, so
|
|
319
|
+
* it is neither the lock container nor a shard, and react-remove-scroll's
|
|
320
|
+
* `shouldPrevent` calls `preventDefault()` on every wheel and touch event it
|
|
321
|
+
* receives — leaving only the rows already on screen reachable, and every
|
|
322
|
+
* other time selectable solely by clicking two rows at a time.
|
|
323
|
+
*
|
|
324
|
+
* Mounting our own lock pushes it to the top of react-remove-scroll's
|
|
325
|
+
* `lockStack`, and the sidecar bails out for any lock that is not the last
|
|
326
|
+
* one, so this panel's scrolling is honoured while the dialog's own lock
|
|
327
|
+
* still holds for the page behind it. It is the same thing Radix `Select`
|
|
328
|
+
* does with its content, and the reason a Select works inside a dialog where
|
|
329
|
+
* this panel did not.
|
|
330
|
+
*
|
|
331
|
+
* Enabled unconditionally rather than only inside a dialog: the panel's
|
|
332
|
+
* position is `fixed` and computed once on open, so locking the page also
|
|
333
|
+
* stops it drifting away from its trigger on a scrollable page.
|
|
334
|
+
*/
|
|
312
335
|
const panel = open ? (
|
|
313
|
-
<
|
|
314
|
-
ref={panelRef}
|
|
315
|
-
className={cn(
|
|
316
|
-
"isolate rounded-xl border border-border bg-popover text-popover-foreground shadow-lg",
|
|
317
|
-
"flex flex-col gap-0"
|
|
318
|
-
)}
|
|
319
|
-
style={{
|
|
320
|
-
position: "fixed",
|
|
321
|
-
top: panelPos.top,
|
|
322
|
-
left: panelPos.left,
|
|
323
|
-
width: PANEL_W,
|
|
324
|
-
zIndex: 20000,
|
|
325
|
-
}}
|
|
326
|
-
>
|
|
327
|
-
{/* Header */}
|
|
328
|
-
<div className="flex items-center gap-1.5 border-b border-border px-4 py-2.5">
|
|
329
|
-
<Clock className="size-3.5 text-muted-foreground" />
|
|
330
|
-
<span className="text-[13px] font-medium text-muted-foreground">
|
|
331
|
-
{value ? displayTime(value, use24Hour) : "—"}
|
|
332
|
-
</span>
|
|
333
|
-
</div>
|
|
334
|
-
|
|
335
|
-
{/* Column labels */}
|
|
336
|
+
<RemoveScroll allowPinchZoom>
|
|
336
337
|
<div
|
|
337
|
-
|
|
338
|
-
|
|
338
|
+
ref={panelRef}
|
|
339
|
+
className={cn(
|
|
340
|
+
"isolate rounded-xl border border-border bg-popover text-popover-foreground shadow-lg",
|
|
341
|
+
"flex flex-col gap-0"
|
|
342
|
+
)}
|
|
343
|
+
style={{
|
|
344
|
+
position: "fixed",
|
|
345
|
+
top: panelPos.top,
|
|
346
|
+
left: panelPos.left,
|
|
347
|
+
width: PANEL_W,
|
|
348
|
+
zIndex: 20000,
|
|
349
|
+
// See DatePicker: a modal Radix Dialog puts `pointer-events: none`
|
|
350
|
+
// on <body>, which this portaled panel would otherwise inherit —
|
|
351
|
+
// the columns rendered but no row could be clicked.
|
|
352
|
+
pointerEvents: "auto",
|
|
353
|
+
}}
|
|
339
354
|
>
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
</span>
|
|
346
|
-
{!use24Hour && (
|
|
347
|
-
<span className="w-16 text-center text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70">
|
|
348
|
-
AM/PM
|
|
355
|
+
{/* Header */}
|
|
356
|
+
<div className="flex items-center gap-1.5 border-b border-border px-4 py-2.5">
|
|
357
|
+
<Clock className="size-3.5 text-muted-foreground" />
|
|
358
|
+
<span className="text-[13px] font-medium text-muted-foreground">
|
|
359
|
+
{value ? displayTime(value, use24Hour) : "—"}
|
|
349
360
|
</span>
|
|
350
|
-
|
|
351
|
-
</div>
|
|
361
|
+
</div>
|
|
352
362
|
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
363
|
+
{/* Column labels */}
|
|
364
|
+
<div
|
|
365
|
+
className="flex items-center justify-around px-2 pt-2 pb-0.5"
|
|
366
|
+
style={{ paddingLeft: 8, paddingRight: use24Hour ? 8 : 8 }}
|
|
367
|
+
>
|
|
368
|
+
<span className="w-16 text-center text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70">
|
|
369
|
+
Hr
|
|
370
|
+
</span>
|
|
371
|
+
<span className="w-16 text-center text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70">
|
|
372
|
+
Min
|
|
373
|
+
</span>
|
|
374
|
+
{!use24Hour && (
|
|
375
|
+
<span className="w-16 text-center text-[11px] font-semibold uppercase tracking-wider text-muted-foreground/70">
|
|
376
|
+
AM/PM
|
|
377
|
+
</span>
|
|
378
|
+
)}
|
|
379
|
+
</div>
|
|
380
|
+
|
|
381
|
+
{/* Columns */}
|
|
382
|
+
<div className="flex items-center justify-around px-2 pb-3">
|
|
383
|
+
<ScrollColumn
|
|
384
|
+
items={hours}
|
|
385
|
+
selected={hour}
|
|
386
|
+
onSelect={handleHourChange}
|
|
387
|
+
renderItem={(h) => pad(h)}
|
|
388
|
+
getKey={(h) => h}
|
|
389
|
+
/>
|
|
390
|
+
<div className="text-[18px] font-light text-muted-foreground/50 pb-0.5">:</div>
|
|
391
|
+
<ScrollColumn
|
|
392
|
+
items={minutes}
|
|
393
|
+
selected={minute}
|
|
394
|
+
onSelect={handleMinuteChange}
|
|
395
|
+
renderItem={(m) => pad(m)}
|
|
396
|
+
getKey={(m) => m}
|
|
397
|
+
/>
|
|
398
|
+
{!use24Hour && (
|
|
399
|
+
<>
|
|
400
|
+
<div className="w-px self-stretch bg-border mx-1" />
|
|
401
|
+
<ScrollColumn
|
|
402
|
+
items={["AM", "PM"] as const}
|
|
403
|
+
selected={period}
|
|
404
|
+
onSelect={handlePeriodChange}
|
|
405
|
+
renderItem={(p) => p}
|
|
406
|
+
getKey={(p) => p}
|
|
407
|
+
/>
|
|
408
|
+
</>
|
|
409
|
+
)}
|
|
410
|
+
</div>
|
|
382
411
|
</div>
|
|
383
|
-
</
|
|
412
|
+
</RemoveScroll>
|
|
384
413
|
) : null;
|
|
385
414
|
|
|
386
415
|
/* ── Merge refs ── */
|