@refraction-ui/react 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -128,7 +128,6 @@ __export(index_exports, {
128
128
  Command: () => Command,
129
129
  CommandEmpty: () => CommandEmpty,
130
130
  CommandGroup: () => CommandGroup,
131
- CommandInput: () => CommandInput,
132
131
  CommandItem: () => CommandItem,
133
132
  CommandList: () => CommandList,
134
133
  CommandSeparator: () => CommandSeparator,
@@ -179,6 +178,7 @@ __export(index_exports, {
179
178
  PRESENCE_STATUS_COLORS: () => STATUS_COLORS,
180
179
  PRESENCE_STATUS_LABELS: () => STATUS_LABELS,
181
180
  Pagination: () => Pagination,
181
+ Payment: () => Payment,
182
182
  Popover: () => Popover,
183
183
  PopoverClose: () => PopoverClose,
184
184
  PopoverContent: () => PopoverContent,
@@ -1160,106 +1160,16 @@ function getAssignableRoles(user) {
1160
1160
  if (hasRole(user, "reviewer")) return ["student"];
1161
1161
  return [];
1162
1162
  }
1163
- function createMockAdapter(initialUser) {
1164
- let currentUser = initialUser ?? null;
1165
- const listeners = /* @__PURE__ */ new Set();
1166
- function notify() {
1167
- for (const fn of listeners) {
1168
- fn(currentUser);
1169
- }
1170
- }
1171
- return {
1172
- async signIn(email, _password) {
1173
- currentUser = {
1174
- uid: "mock-" + email,
1175
- email,
1176
- displayName: email.split("@")[0],
1177
- photoURL: null,
1178
- roles: ["student"]
1179
- };
1180
- notify();
1181
- return currentUser;
1182
- },
1183
- async signInWithOAuth(_provider) {
1184
- currentUser = {
1185
- uid: "mock-oauth",
1186
- email: "oauth@example.com",
1187
- displayName: "OAuth User",
1188
- photoURL: null,
1189
- roles: ["student"]
1190
- };
1191
- notify();
1192
- return currentUser;
1193
- },
1194
- async signUp(email, _password, displayName) {
1195
- currentUser = {
1196
- uid: "mock-" + email,
1197
- email,
1198
- displayName,
1199
- photoURL: null,
1200
- roles: ["student"]
1201
- };
1202
- notify();
1203
- return currentUser;
1204
- },
1205
- async signOut() {
1206
- currentUser = null;
1207
- notify();
1208
- },
1209
- async resetPassword(_email) {
1210
- },
1211
- async getToken() {
1212
- return currentUser ? "mock-token-" + currentUser.uid : null;
1213
- },
1214
- onAuthStateChange(callback) {
1215
- listeners.add(callback);
1216
- callback(currentUser);
1217
- return () => {
1218
- listeners.delete(callback);
1219
- };
1220
- }
1221
- };
1222
- }
1223
- function resolveAdapter(provider) {
1224
- const resolved = provider ?? detectProvider();
1225
- switch (resolved) {
1226
- case "firebase":
1227
- if (typeof console !== "undefined") {
1228
- console.warn("[refraction-ui/auth] Firebase adapter not yet implemented. Using mock adapter.");
1229
- }
1230
- return createMockAdapter();
1231
- case "supabase":
1232
- if (typeof console !== "undefined") {
1233
- console.warn("[refraction-ui/auth] Supabase adapter not yet implemented. Using mock adapter.");
1234
- }
1235
- return createMockAdapter();
1236
- case "mock":
1237
- return createMockAdapter();
1238
- case "none":
1239
- default:
1240
- return createMockAdapter();
1241
- }
1242
- }
1243
- function detectProvider() {
1244
- const env = typeof process !== "undefined" ? process.env : {};
1245
- const explicit = env["REFRACTION_AUTH_PROVIDER"];
1246
- if (explicit) return explicit;
1247
- if (env["FIREBASE_API_KEY"] || env["NEXT_PUBLIC_FIREBASE_API_KEY"]) {
1248
- return "firebase";
1249
- }
1250
- if (env["SUPABASE_URL"] || env["NEXT_PUBLIC_SUPABASE_URL"]) {
1251
- return "supabase";
1252
- }
1253
- return "none";
1254
- }
1255
1163
 
1256
1164
  // ../react-auth/dist/index.js
1257
1165
  var AuthContext = React41__namespace.createContext(null);
1258
1166
  function AuthProvider({ children, ...config }) {
1259
1167
  const authRef = React41__namespace.useRef(null);
1260
1168
  if (!authRef.current) {
1261
- const adapter = resolveAdapter(config.provider);
1262
- authRef.current = createAuth(adapter, config);
1169
+ if (!config.adapter) {
1170
+ throw new Error("[refraction-ui/react-auth] You must provide an `adapter` to AuthProvider.");
1171
+ }
1172
+ authRef.current = createAuth(config.adapter, config);
1263
1173
  }
1264
1174
  const [state, setState] = React41__namespace.useState(() => authRef.current.getState());
1265
1175
  React41__namespace.useEffect(() => {
@@ -12348,6 +12258,259 @@ var CardGrid = React41__namespace.forwardRef(
12348
12258
  );
12349
12259
  CardGrid.displayName = "CardGrid";
12350
12260
 
12261
+ // ../payment/dist/index.js
12262
+ function createPayment(props = {}) {
12263
+ return {
12264
+ props: {
12265
+ ...props,
12266
+ "data-slot": "payment"
12267
+ }
12268
+ };
12269
+ }
12270
+ var Payment = React41__namespace.forwardRef(
12271
+ ({ className, disabled, ...props }, ref) => {
12272
+ const api = createPayment({ disabled });
12273
+ return /* @__PURE__ */ jsxRuntime.jsx(
12274
+ "div",
12275
+ {
12276
+ ref,
12277
+ className: cn(
12278
+ "w-full max-w-md mx-auto p-6 border border-border rounded-xl bg-card text-card-foreground shadow-sm",
12279
+ disabled && "opacity-50 pointer-events-none",
12280
+ className
12281
+ ),
12282
+ ...api.props,
12283
+ ...props
12284
+ }
12285
+ );
12286
+ }
12287
+ );
12288
+ Payment.displayName = "Payment";
12289
+ var PaymentHeader = React41__namespace.forwardRef(
12290
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("mb-6 flex flex-col gap-1.5", className), ...props })
12291
+ );
12292
+ PaymentHeader.displayName = "PaymentHeader";
12293
+ var PaymentTitle = React41__namespace.forwardRef(
12294
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("h3", { ref, className: cn("text-xl font-semibold leading-none tracking-tight", className), ...props })
12295
+ );
12296
+ PaymentTitle.displayName = "PaymentTitle";
12297
+ var PaymentDescription = React41__namespace.forwardRef(
12298
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("p", { ref, className: cn("text-sm text-muted-foreground", className), ...props })
12299
+ );
12300
+ PaymentDescription.displayName = "PaymentDescription";
12301
+ var PaymentContent = React41__namespace.forwardRef(
12302
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("flex flex-col gap-4", className), ...props })
12303
+ );
12304
+ PaymentContent.displayName = "PaymentContent";
12305
+ var PaymentFooter = React41__namespace.forwardRef(
12306
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("mt-6 flex flex-col gap-3", className), ...props })
12307
+ );
12308
+ PaymentFooter.displayName = "PaymentFooter";
12309
+ var PaymentButton = React41__namespace.forwardRef(
12310
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
12311
+ "button",
12312
+ {
12313
+ ref,
12314
+ className: cn(
12315
+ "inline-flex w-full items-center justify-center whitespace-nowrap rounded-md bg-primary px-4 py-2.5 text-sm font-medium text-primary-foreground shadow transition-colors hover:bg-primary/90 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
12316
+ className
12317
+ ),
12318
+ ...props
12319
+ }
12320
+ )
12321
+ );
12322
+ PaymentButton.displayName = "PaymentButton";
12323
+
12324
+ // ../command-input/dist/index.js
12325
+ var CommandInput2 = class {
12326
+ state = {
12327
+ nodes: [],
12328
+ rawText: "",
12329
+ cursorPosition: 0,
12330
+ activeTrigger: null,
12331
+ activeCommandText: null
12332
+ };
12333
+ options;
12334
+ constructor(options) {
12335
+ this.options = { ...options };
12336
+ }
12337
+ handleInput(text, cursorPosition) {
12338
+ this.state.rawText = text;
12339
+ this.state.cursorPosition = cursorPosition;
12340
+ this.parseInput();
12341
+ this.notifyStateChange();
12342
+ }
12343
+ handleKeyDown(key, event) {
12344
+ if (this.state.activeTrigger) {
12345
+ if (key === "Escape") {
12346
+ if (event) event.preventDefault();
12347
+ this.state.activeTrigger = null;
12348
+ this.state.activeCommandText = null;
12349
+ if (this.options.onCommandCancel) {
12350
+ this.options.onCommandCancel();
12351
+ }
12352
+ this.notifyStateChange();
12353
+ } else if (key === "Enter") {
12354
+ if (event) event.preventDefault();
12355
+ const trigger = this.state.activeTrigger;
12356
+ const text = this.state.activeCommandText || "";
12357
+ this.state.activeTrigger = null;
12358
+ this.state.activeCommandText = null;
12359
+ if (this.options.onCommandCommit) {
12360
+ this.options.onCommandCommit(trigger, text);
12361
+ }
12362
+ this.notifyStateChange();
12363
+ }
12364
+ }
12365
+ }
12366
+ get value() {
12367
+ return this.state.nodes;
12368
+ }
12369
+ getState() {
12370
+ return { ...this.state };
12371
+ }
12372
+ parseInput() {
12373
+ const { rawText, cursorPosition } = this.state;
12374
+ this.state.activeTrigger = null;
12375
+ this.state.activeCommandText = null;
12376
+ for (let i = cursorPosition - 1; i >= 0; i--) {
12377
+ const char = rawText[i];
12378
+ const matchedTrigger = this.options.triggers.find((t) => t.char === char);
12379
+ if (matchedTrigger) {
12380
+ const isStartOfWord = i === 0 || /\\s/.test(rawText[i - 1]);
12381
+ if (isStartOfWord) {
12382
+ const commandText = rawText.slice(i + 1, cursorPosition);
12383
+ if (!/\\s/.test(commandText)) {
12384
+ let isValid = true;
12385
+ if (matchedTrigger.pattern) {
12386
+ isValid = matchedTrigger.pattern.test(commandText);
12387
+ }
12388
+ if (isValid) {
12389
+ this.state.activeTrigger = matchedTrigger;
12390
+ this.state.activeCommandText = commandText;
12391
+ if (this.options.onCommandTriggered) {
12392
+ this.options.onCommandTriggered(matchedTrigger, commandText);
12393
+ }
12394
+ }
12395
+ }
12396
+ }
12397
+ break;
12398
+ }
12399
+ if (/\\s/.test(char)) {
12400
+ break;
12401
+ }
12402
+ }
12403
+ const nodes = [];
12404
+ if (this.options.triggers.length === 0) {
12405
+ nodes.push({ type: "text", text: rawText });
12406
+ this.state.nodes = nodes;
12407
+ return;
12408
+ }
12409
+ const triggerChars = this.options.triggers.map((t) => t.char.replace(/[.*+?^\${}()|[\\]\\\\]/g, "\\\\$&"));
12410
+ const patternStr = `(^|\\\\s)(${triggerChars.join("|")})([^\\\\s]*)`;
12411
+ const regex = new RegExp(patternStr, "g");
12412
+ let currentIndex = 0;
12413
+ let match;
12414
+ while ((match = regex.exec(rawText)) !== null) {
12415
+ const precedingWhitespace = match[1];
12416
+ const triggerChar = match[2];
12417
+ const commandText = match[3];
12418
+ const matchStart = match.index;
12419
+ const triggerStart = matchStart + precedingWhitespace.length;
12420
+ const triggerConfig = this.options.triggers.find((t) => t.char === triggerChar);
12421
+ let isValid = true;
12422
+ if (triggerConfig?.pattern && commandText.length > 0) {
12423
+ isValid = triggerConfig.pattern.test(commandText);
12424
+ }
12425
+ if (isValid) {
12426
+ if (triggerStart > currentIndex) {
12427
+ nodes.push({ type: "text", text: rawText.slice(currentIndex, triggerStart) });
12428
+ }
12429
+ nodes.push({ type: "command", trigger: triggerChar, text: commandText });
12430
+ currentIndex = regex.lastIndex;
12431
+ }
12432
+ }
12433
+ if (currentIndex < rawText.length) {
12434
+ nodes.push({ type: "text", text: rawText.slice(currentIndex) });
12435
+ }
12436
+ this.state.nodes = nodes;
12437
+ }
12438
+ notifyStateChange() {
12439
+ if (this.options.onStateChange) {
12440
+ this.options.onStateChange({ ...this.state });
12441
+ }
12442
+ }
12443
+ };
12444
+ var CommandInput3 = React41.forwardRef(
12445
+ ({
12446
+ value = "",
12447
+ onChange,
12448
+ triggers = [],
12449
+ renderPopover,
12450
+ className,
12451
+ ...props
12452
+ }, ref) => {
12453
+ const localRef = React41.useRef(null);
12454
+ const containerRef = ref || localRef;
12455
+ const [popoverState, setPopoverState] = React41.useState({
12456
+ isOpen: false,
12457
+ trigger: "",
12458
+ search: "",
12459
+ position: { top: 0, left: 0 }
12460
+ });
12461
+ const coreRef = React41.useRef(null);
12462
+ React41.useEffect(() => {
12463
+ if (containerRef.current && !coreRef.current) {
12464
+ coreRef.current = new CommandInput2({
12465
+ triggers,
12466
+ onCommandTriggered: (trigger, search) => {
12467
+ setPopoverState({
12468
+ isOpen: true,
12469
+ trigger: trigger.char,
12470
+ search,
12471
+ position: { top: 0, left: 0 }
12472
+ });
12473
+ },
12474
+ onCommandCancel: () => {
12475
+ setPopoverState((prev) => ({ ...prev, isOpen: false }));
12476
+ },
12477
+ onStateChange: (state) => {
12478
+ onChange?.(state.rawText);
12479
+ }
12480
+ });
12481
+ }
12482
+ }, [triggers, onChange]);
12483
+ React41.useEffect(() => {
12484
+ if (containerRef.current && containerRef.current.innerHTML !== value && coreRef.current) {
12485
+ containerRef.current.innerHTML = value;
12486
+ }
12487
+ }, [value]);
12488
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative w-full", className), children: [
12489
+ /* @__PURE__ */ jsxRuntime.jsx(
12490
+ "div",
12491
+ {
12492
+ ref: containerRef,
12493
+ contentEditable: true,
12494
+ suppressContentEditableWarning: true,
12495
+ className: "w-full min-h-[40px] p-2 border border-gray-300 rounded focus:outline-none focus:ring-2 focus:ring-blue-500",
12496
+ onInput: (e) => {
12497
+ coreRef.current?.handleInput(e.currentTarget.textContent || "", 0);
12498
+ },
12499
+ onKeyDown: (e) => {
12500
+ coreRef.current?.handleKeyDown(e.key, e);
12501
+ },
12502
+ ...props
12503
+ }
12504
+ ),
12505
+ renderPopover && renderPopover({
12506
+ ...popoverState,
12507
+ close: () => setPopoverState((prev) => ({ ...prev, isOpen: false }))
12508
+ })
12509
+ ] });
12510
+ }
12511
+ );
12512
+ CommandInput3.displayName = "CommandInput";
12513
+
12351
12514
  exports.Accordion = Accordion;
12352
12515
  exports.AccordionContent = AccordionContent;
12353
12516
  exports.AccordionItem = AccordionItem;
@@ -12389,7 +12552,6 @@ exports.CollapsibleTrigger = CollapsibleTrigger;
12389
12552
  exports.Command = Command;
12390
12553
  exports.CommandEmpty = CommandEmpty;
12391
12554
  exports.CommandGroup = CommandGroup;
12392
- exports.CommandInput = CommandInput;
12393
12555
  exports.CommandItem = CommandItem;
12394
12556
  exports.CommandList = CommandList;
12395
12557
  exports.CommandSeparator = CommandSeparator;
@@ -12440,6 +12602,7 @@ exports.OtpInput = OtpInput;
12440
12602
  exports.PRESENCE_STATUS_COLORS = STATUS_COLORS;
12441
12603
  exports.PRESENCE_STATUS_LABELS = STATUS_LABELS;
12442
12604
  exports.Pagination = Pagination;
12605
+ exports.Payment = Payment;
12443
12606
  exports.Popover = Popover;
12444
12607
  exports.PopoverClose = PopoverClose;
12445
12608
  exports.PopoverContent = PopoverContent;