@stableflow/pay-ui 0.2.0-beta-bb77113a4d-20261012 → 0.2.1

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.
@@ -157,7 +157,7 @@ function DateRangePicker(props) {
157
157
  }
158
158
  commit(calendarRangeFromPicks(draftStart, day));
159
159
  };
160
- return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-block min-w-0", className), children: [
160
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative inline-flex w-max max-w-full", className), children: [
161
161
  /* @__PURE__ */ jsxs(
162
162
  "button",
163
163
  {
@@ -171,13 +171,13 @@ function DateRangePicker(props) {
171
171
  setDraftStart(null);
172
172
  },
173
173
  className: cn(
174
- "inline-flex cursor-pointer h-9 w-full min-w-0 items-center justify-between gap-2 overflow-hidden rounded-[6px] border border-[#E3E3E3] bg-white px-3 text-sm font-medium text-black outline-none",
174
+ "inline-flex cursor-pointer h-9 w-max max-w-full items-center gap-2 whitespace-nowrap rounded-[6px] border border-[#E3E3E3] bg-white px-3 text-sm font-medium text-black outline-none",
175
175
  fontSans,
176
176
  triggerClassName
177
177
  ),
178
178
  children: [
179
- /* @__PURE__ */ jsx("span", { className: "min-w-0 shrink truncate text-[#aaa]", children: "Time" }),
180
- /* @__PURE__ */ jsx("span", { className: "flex min-w-0 flex-1 items-center justify-end gap-2 truncate text-right", children: formatDateRangeLabel(value) }),
179
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-[#aaa]", children: "Time" }),
180
+ /* @__PURE__ */ jsx("span", { className: "shrink-0", children: formatDateRangeLabel(value) }),
181
181
  /* @__PURE__ */ jsx(IconArrowDown, { className: cn("h-1.5 w-2.75 shrink-0 text-black transition-transform", open && "rotate-180") })
182
182
  ]
183
183
  }
@@ -221,7 +221,7 @@ function DateRangePicker(props) {
221
221
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1", children: DATE_RANGE_WEEKDAY_LABELS.map((label) => /* @__PURE__ */ jsx("div", { className: "text-center text-[11px] font-medium text-[#aaa]", children: label }, label)) }),
222
222
  /* @__PURE__ */ jsx("div", { className: "grid grid-cols-7 gap-1", children: days.map((day) => {
223
223
  const inMonth = isSameMonth(day, viewMonth);
224
- const selected = isSameDay2(day, value.from) || isSameDay2(day, value.to) || (draftStart ? isSameDay2(day, draftStart) : false);
224
+ const selected = draftStart ? isSameDay2(day, draftStart) : isSameDay2(day, value.from) || isSameDay2(day, value.to);
225
225
  const inRange = !draftStart && isWithinInterval(day, { start: value.from, end: value.to });
226
226
  return /* @__PURE__ */ jsx(
227
227
  "button",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/date-range-picker/DateRangePicker.tsx","../../src/date-range-picker/config.ts","../../src/date-range-picker/utils.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n addMonths,\n eachDayOfInterval,\n endOfMonth,\n endOfWeek,\n format,\n isSameDay,\n isSameMonth,\n isWithinInterval,\n startOfMonth,\n startOfWeek,\n} from \"date-fns\";\nimport { IconArrowDown } from \"../icons/outline/arrow-down\";\nimport { cn } from \"../lib/cn\";\nimport { fontSans } from \"../lib/font\";\nimport { floatingLayerZIndex } from \"../overlay/stack\";\nimport { FLOATING_ALIGN, FLOATING_SIDE, useFloatingPosition } from \"../overlay/use-floating-position\";\nimport { DATE_RANGE_PRESET_OPTIONS, DATE_RANGE_WEEKDAY_LABELS } from \"./config\";\nimport { calendarRangeFromPicks, formatDateRangeLabel, lastNDaysRange, type DateRangeValue } from \"./utils\";\n\nexport type { DateRangeValue } from \"./utils\";\n\nexport function DateRangePicker(props: {\n value: DateRangeValue;\n onChange: (range: DateRangeValue) => void;\n className?: string;\n triggerClassName?: string;\n}) {\n const { value, onChange, className, triggerClassName } = props;\n const triggerRef = useRef<HTMLButtonElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const [open, setOpen] = useState(false);\n const [viewMonth, setViewMonth] = useState(() => startOfMonth(value.to));\n const [draftStart, setDraftStart] = useState<Date | null>(null);\n const panelStyle = useFloatingPosition({\n open,\n triggerRef,\n panelRef,\n side: FLOATING_SIDE.Bottom,\n align: FLOATING_ALIGN.Start,\n offset: 6,\n });\n\n useEffect(() => {\n if (open) setViewMonth(startOfMonth(value.to));\n }, [open, value.to]);\n\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (event: MouseEvent) => {\n const target = event.target as Node | null;\n if (!target) return;\n if (triggerRef.current?.contains(target)) return;\n if (panelRef.current?.contains(target)) return;\n setOpen(false);\n setDraftStart(null);\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setOpen(false);\n setDraftStart(null);\n }\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"mousedown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [open]);\n\n const days = useMemo(() => {\n const monthStart = startOfMonth(viewMonth);\n return eachDayOfInterval({\n start: startOfWeek(monthStart),\n end: endOfWeek(endOfMonth(monthStart)),\n });\n }, [viewMonth]);\n\n const commit = (range: DateRangeValue) => {\n onChange(range);\n setDraftStart(null);\n setOpen(false);\n };\n\n const pickDay = (day: Date) => {\n if (!draftStart) {\n setDraftStart(day);\n return;\n }\n commit(calendarRangeFromPicks(draftStart, day));\n };\n\n return (\n <div className={cn(\"relative inline-block min-w-0\", className)}>\n <button\n ref={triggerRef}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-label=\"Select time range\"\n onClick={() => {\n setOpen((current) => !current);\n setDraftStart(null);\n }}\n className={cn(\n \"inline-flex cursor-pointer h-9 w-full min-w-0 items-center justify-between gap-2 overflow-hidden rounded-[6px] border border-[#E3E3E3] bg-white px-3 text-sm font-medium text-black outline-none\",\n fontSans,\n triggerClassName,\n )}\n >\n <span className=\"min-w-0 shrink truncate text-[#aaa]\">Time</span>\n <span className=\"flex min-w-0 flex-1 items-center justify-end gap-2 truncate text-right\">\n {formatDateRangeLabel(value)}\n </span>\n <IconArrowDown className={cn(\"h-1.5 w-2.75 shrink-0 text-black transition-transform\", open && \"rotate-180\")} />\n </button>\n {open && typeof document !== \"undefined\"\n ? createPortal(\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-label=\"Date range\"\n style={{ ...panelStyle, zIndex: floatingLayerZIndex() }}\n className={cn(\n \"w-[min(320px,calc(100vw-32px))] rounded-[16px] border border-black/10 bg-white p-4 shadow-[0_8px_24px_rgba(0,0,0,0.08)]\",\n fontSans,\n )}\n >\n <div className=\"mb-3 flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n onClick={() => setViewMonth((month) => addMonths(month, -1))}\n className=\"inline-flex size-8 cursor-pointer items-center justify-center rounded-full border-0 bg-transparent p-0 text-[#606060] hover:bg-black/5\"\n >\n <IconArrowDown className=\"h-1.5 w-2.75 rotate-90\" />\n </button>\n <span className=\"text-sm font-semibold text-black\">{format(viewMonth, \"yyyy MMM\")}</span>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n onClick={() => setViewMonth((month) => addMonths(month, 1))}\n className=\"inline-flex size-8 cursor-pointer items-center justify-center rounded-full border-0 bg-transparent p-0 text-[#606060] hover:bg-black/5\"\n >\n <IconArrowDown className=\"h-1.5 w-2.75 -rotate-90\" />\n </button>\n </div>\n <div className=\"grid grid-cols-7 gap-1\">\n {DATE_RANGE_WEEKDAY_LABELS.map((label) => (\n <div key={label} className=\"text-center text-[11px] font-medium text-[#aaa]\">\n {label}\n </div>\n ))}\n </div>\n <div className=\"grid grid-cols-7 gap-1\">\n {days.map((day) => {\n const inMonth = isSameMonth(day, viewMonth);\n const selected = isSameDay(day, value.from) || isSameDay(day, value.to) || (draftStart ? isSameDay(day, draftStart) : false);\n const inRange = !draftStart && isWithinInterval(day, { start: value.from, end: value.to });\n return (\n <button\n key={day.toISOString()}\n type=\"button\"\n onClick={() => pickDay(day)}\n className={cn(\n \"h-8 cursor-pointer rounded-[8px] border-0 bg-transparent text-[13px] font-medium text-black hover:bg-black/5\",\n !inMonth && \"text-[#ccc]\",\n inRange && !selected && \"bg-black/5\",\n selected && \"bg-black text-white hover:bg-black\",\n )}\n >\n {format(day, \"d\")}\n </button>\n );\n })}\n </div>\n <div className=\"mt-3 flex flex-col gap-1 border-t border-black/10 pt-2\">\n {DATE_RANGE_PRESET_OPTIONS.map((option) => (\n <button\n key={option.days}\n type=\"button\"\n onClick={() => commit(lastNDaysRange(option.days))}\n className=\"cursor-pointer rounded-[8px] border-0 bg-transparent px-2 py-1.5 text-left text-sm font-medium text-black hover:bg-black/5\"\n >\n {option.label}\n </button>\n ))}\n </div>\n </div>,\n document.body,\n )\n : null}\n </div>\n );\n}\n\nexport default DateRangePicker;\n","export const DATE_RANGE_WEEKDAY_LABELS = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"] as const;\n\nexport const DATE_RANGE_PRESET = {\n Days30: 30,\n Days7: 7,\n Days1: 1,\n} as const;\n\nexport const DATE_RANGE_PRESET_OPTIONS = [\n { days: DATE_RANGE_PRESET.Days30, label: \"Last 30 days\" },\n { days: DATE_RANGE_PRESET.Days7, label: \"Last 7 days\" },\n { days: DATE_RANGE_PRESET.Days1, label: \"Last 1 day\" },\n] as const;\n","import {\n differenceInCalendarDays,\n endOfDay,\n format,\n isSameDay,\n startOfDay,\n subDays,\n} from \"date-fns\";\nimport { DATE_RANGE_PRESET_OPTIONS } from \"./config\";\n\nexport type DateRangeValue = {\n from: Date;\n to: Date;\n};\n\nexport function calendarRangeFromPicks(start: Date, end: Date): DateRangeValue {\n if (isSameDay(start, end)) {\n return { from: startOfDay(end), to: endOfDay(end) };\n }\n const from = start.getTime() <= end.getTime() ? start : end;\n const to = start.getTime() <= end.getTime() ? end : start;\n return { from: startOfDay(from), to: endOfDay(to) };\n}\n\nexport function lastNDaysRange(days: number, now: Date = new Date()): DateRangeValue {\n return {\n from: startOfDay(subDays(now, days - 1)),\n to: endOfDay(now),\n };\n}\n\nexport function matchesLastNDays(range: DateRangeValue, days: number, now: Date = new Date()) {\n const expected = lastNDaysRange(days, now);\n return isSameDay(range.from, expected.from) && isSameDay(range.to, expected.to);\n}\n\nexport function formatDateRangeLabel(range: DateRangeValue, now: Date = new Date()) {\n const preset = DATE_RANGE_PRESET_OPTIONS.find((option) =>\n matchesLastNDays(range, option.days, now),\n );\n if (preset) return preset.label;\n if (isSameDay(range.from, range.to)) return format(range.from, \"MMM d, yyyy\");\n return `${format(range.from, \"MMM d, yyyy\")} – ${format(range.to, \"MMM d, yyyy\")}`;\n}\n\nexport function isInDateRange(iso: string, range: DateRangeValue) {\n const time = new Date(iso).getTime();\n if (Number.isNaN(time)) return true;\n return time >= range.from.getTime() && time <= range.to.getTime();\n}\n\nexport function rangeToUnixSeconds(range: DateRangeValue) {\n return {\n start_time: Math.floor(range.from.getTime() / 1000),\n end_time: Math.floor(range.to.getTime() / 1000),\n };\n}\n\nexport function dateRangeDayCount(range: DateRangeValue) {\n return differenceInCalendarDays(range.to, range.from) + 1;\n}\n"],"mappings":"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","names":["format","isSameDay","format","isSameDay"]}
1
+ {"version":3,"sources":["../../src/date-range-picker/DateRangePicker.tsx","../../src/date-range-picker/config.ts","../../src/date-range-picker/utils.ts"],"sourcesContent":["import { useEffect, useMemo, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport {\n addMonths,\n eachDayOfInterval,\n endOfMonth,\n endOfWeek,\n format,\n isSameDay,\n isSameMonth,\n isWithinInterval,\n startOfMonth,\n startOfWeek,\n} from \"date-fns\";\nimport { IconArrowDown } from \"../icons/outline/arrow-down\";\nimport { cn } from \"../lib/cn\";\nimport { fontSans } from \"../lib/font\";\nimport { floatingLayerZIndex } from \"../overlay/stack\";\nimport { FLOATING_ALIGN, FLOATING_SIDE, useFloatingPosition } from \"../overlay/use-floating-position\";\nimport { DATE_RANGE_PRESET_OPTIONS, DATE_RANGE_WEEKDAY_LABELS } from \"./config\";\nimport { calendarRangeFromPicks, formatDateRangeLabel, lastNDaysRange, type DateRangeValue } from \"./utils\";\n\nexport type { DateRangeValue } from \"./utils\";\n\nexport function DateRangePicker(props: {\n value: DateRangeValue;\n onChange: (range: DateRangeValue) => void;\n className?: string;\n triggerClassName?: string;\n}) {\n const { value, onChange, className, triggerClassName } = props;\n const triggerRef = useRef<HTMLButtonElement>(null);\n const panelRef = useRef<HTMLDivElement>(null);\n const [open, setOpen] = useState(false);\n const [viewMonth, setViewMonth] = useState(() => startOfMonth(value.to));\n const [draftStart, setDraftStart] = useState<Date | null>(null);\n const panelStyle = useFloatingPosition({\n open,\n triggerRef,\n panelRef,\n side: FLOATING_SIDE.Bottom,\n align: FLOATING_ALIGN.Start,\n offset: 6,\n });\n\n useEffect(() => {\n if (open) setViewMonth(startOfMonth(value.to));\n }, [open, value.to]);\n\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (event: MouseEvent) => {\n const target = event.target as Node | null;\n if (!target) return;\n if (triggerRef.current?.contains(target)) return;\n if (panelRef.current?.contains(target)) return;\n setOpen(false);\n setDraftStart(null);\n };\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setOpen(false);\n setDraftStart(null);\n }\n };\n document.addEventListener(\"mousedown\", onPointerDown);\n document.addEventListener(\"keydown\", onKeyDown);\n return () => {\n document.removeEventListener(\"mousedown\", onPointerDown);\n document.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [open]);\n\n const days = useMemo(() => {\n const monthStart = startOfMonth(viewMonth);\n return eachDayOfInterval({\n start: startOfWeek(monthStart),\n end: endOfWeek(endOfMonth(monthStart)),\n });\n }, [viewMonth]);\n\n const commit = (range: DateRangeValue) => {\n onChange(range);\n setDraftStart(null);\n setOpen(false);\n };\n\n const pickDay = (day: Date) => {\n if (!draftStart) {\n setDraftStart(day);\n return;\n }\n commit(calendarRangeFromPicks(draftStart, day));\n };\n\n return (\n <div className={cn(\"relative inline-flex w-max max-w-full\", className)}>\n <button\n ref={triggerRef}\n type=\"button\"\n aria-haspopup=\"dialog\"\n aria-expanded={open}\n aria-label=\"Select time range\"\n onClick={() => {\n setOpen((current) => !current);\n setDraftStart(null);\n }}\n className={cn(\n \"inline-flex cursor-pointer h-9 w-max max-w-full items-center gap-2 whitespace-nowrap rounded-[6px] border border-[#E3E3E3] bg-white px-3 text-sm font-medium text-black outline-none\",\n fontSans,\n triggerClassName,\n )}\n >\n <span className=\"shrink-0 text-[#aaa]\">Time</span>\n <span className=\"shrink-0\">{formatDateRangeLabel(value)}</span>\n <IconArrowDown className={cn(\"h-1.5 w-2.75 shrink-0 text-black transition-transform\", open && \"rotate-180\")} />\n </button>\n {open && typeof document !== \"undefined\"\n ? createPortal(\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-label=\"Date range\"\n style={{ ...panelStyle, zIndex: floatingLayerZIndex() }}\n className={cn(\n \"w-[min(320px,calc(100vw-32px))] rounded-[16px] border border-black/10 bg-white p-4 shadow-[0_8px_24px_rgba(0,0,0,0.08)]\",\n fontSans,\n )}\n >\n <div className=\"mb-3 flex items-center justify-between\">\n <button\n type=\"button\"\n aria-label=\"Previous month\"\n onClick={() => setViewMonth((month) => addMonths(month, -1))}\n className=\"inline-flex size-8 cursor-pointer items-center justify-center rounded-full border-0 bg-transparent p-0 text-[#606060] hover:bg-black/5\"\n >\n <IconArrowDown className=\"h-1.5 w-2.75 rotate-90\" />\n </button>\n <span className=\"text-sm font-semibold text-black\">{format(viewMonth, \"yyyy MMM\")}</span>\n <button\n type=\"button\"\n aria-label=\"Next month\"\n onClick={() => setViewMonth((month) => addMonths(month, 1))}\n className=\"inline-flex size-8 cursor-pointer items-center justify-center rounded-full border-0 bg-transparent p-0 text-[#606060] hover:bg-black/5\"\n >\n <IconArrowDown className=\"h-1.5 w-2.75 -rotate-90\" />\n </button>\n </div>\n <div className=\"grid grid-cols-7 gap-1\">\n {DATE_RANGE_WEEKDAY_LABELS.map((label) => (\n <div key={label} className=\"text-center text-[11px] font-medium text-[#aaa]\">\n {label}\n </div>\n ))}\n </div>\n <div className=\"grid grid-cols-7 gap-1\">\n {days.map((day) => {\n const inMonth = isSameMonth(day, viewMonth);\n const selected = draftStart\n ? isSameDay(day, draftStart)\n : isSameDay(day, value.from) || isSameDay(day, value.to);\n const inRange = !draftStart && isWithinInterval(day, { start: value.from, end: value.to });\n return (\n <button\n key={day.toISOString()}\n type=\"button\"\n onClick={() => pickDay(day)}\n className={cn(\n \"h-8 cursor-pointer rounded-[8px] border-0 bg-transparent text-[13px] font-medium text-black hover:bg-black/5\",\n !inMonth && \"text-[#ccc]\",\n inRange && !selected && \"bg-black/5\",\n selected && \"bg-black text-white hover:bg-black\",\n )}\n >\n {format(day, \"d\")}\n </button>\n );\n })}\n </div>\n <div className=\"mt-3 flex flex-col gap-1 border-t border-black/10 pt-2\">\n {DATE_RANGE_PRESET_OPTIONS.map((option) => (\n <button\n key={option.days}\n type=\"button\"\n onClick={() => commit(lastNDaysRange(option.days))}\n className=\"cursor-pointer rounded-[8px] border-0 bg-transparent px-2 py-1.5 text-left text-sm font-medium text-black hover:bg-black/5\"\n >\n {option.label}\n </button>\n ))}\n </div>\n </div>,\n document.body,\n )\n : null}\n </div>\n );\n}\n\nexport default DateRangePicker;\n","export const DATE_RANGE_WEEKDAY_LABELS = [\"Su\", \"Mo\", \"Tu\", \"We\", \"Th\", \"Fr\", \"Sa\"] as const;\n\nexport const DATE_RANGE_PRESET = {\n Days30: 30,\n Days7: 7,\n Days1: 1,\n} as const;\n\nexport const DATE_RANGE_PRESET_OPTIONS = [\n { days: DATE_RANGE_PRESET.Days30, label: \"Last 30 days\" },\n { days: DATE_RANGE_PRESET.Days7, label: \"Last 7 days\" },\n { days: DATE_RANGE_PRESET.Days1, label: \"Last 1 day\" },\n] as const;\n","import {\n differenceInCalendarDays,\n endOfDay,\n format,\n isSameDay,\n startOfDay,\n subDays,\n} from \"date-fns\";\nimport { DATE_RANGE_PRESET_OPTIONS } from \"./config\";\n\nexport type DateRangeValue = {\n from: Date;\n to: Date;\n};\n\nexport function calendarRangeFromPicks(start: Date, end: Date): DateRangeValue {\n if (isSameDay(start, end)) {\n return { from: startOfDay(end), to: endOfDay(end) };\n }\n const from = start.getTime() <= end.getTime() ? start : end;\n const to = start.getTime() <= end.getTime() ? end : start;\n return { from: startOfDay(from), to: endOfDay(to) };\n}\n\nexport function lastNDaysRange(days: number, now: Date = new Date()): DateRangeValue {\n return {\n from: startOfDay(subDays(now, days - 1)),\n to: endOfDay(now),\n };\n}\n\nexport function matchesLastNDays(range: DateRangeValue, days: number, now: Date = new Date()) {\n const expected = lastNDaysRange(days, now);\n return isSameDay(range.from, expected.from) && isSameDay(range.to, expected.to);\n}\n\nexport function formatDateRangeLabel(range: DateRangeValue, now: Date = new Date()) {\n const preset = DATE_RANGE_PRESET_OPTIONS.find((option) =>\n matchesLastNDays(range, option.days, now),\n );\n if (preset) return preset.label;\n if (isSameDay(range.from, range.to)) return format(range.from, \"MMM d, yyyy\");\n return `${format(range.from, \"MMM d, yyyy\")} – ${format(range.to, \"MMM d, yyyy\")}`;\n}\n\nexport function isInDateRange(iso: string, range: DateRangeValue) {\n const time = new Date(iso).getTime();\n if (Number.isNaN(time)) return true;\n return time >= range.from.getTime() && time <= range.to.getTime();\n}\n\nexport function rangeToUnixSeconds(range: DateRangeValue) {\n return {\n start_time: Math.floor(range.from.getTime() / 1000),\n end_time: Math.floor(range.to.getTime() / 1000),\n };\n}\n\nexport function dateRangeDayCount(range: DateRangeValue) {\n return differenceInCalendarDays(range.to, range.from) + 1;\n}\n"],"mappings":"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","names":["format","isSameDay","format","isSameDay"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stableflow/pay-ui",
3
- "version": "0.2.0-beta-bb77113a4d-20261012",
3
+ "version": "0.2.1",
4
4
  "description": "Presentational React components and icons for StableFlow Pay.",
5
5
  "keywords": [
6
6
  "stableflow",