@layerfi/components 0.1.0 → 0.1.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.
package/dist/index.js CHANGED
@@ -32,6 +32,7 @@ var src_exports = {};
32
32
  __export(src_exports, {
33
33
  BalanceSheet: () => BalanceSheet,
34
34
  BankTransactions: () => BankTransactions,
35
+ ChartOfAccounts: () => ChartOfAccounts,
35
36
  Hello: () => Hello,
36
37
  LayerProvider: () => LayerProvider,
37
38
  ProfitAndLoss: () => ProfitAndLoss
@@ -39,7 +40,7 @@ __export(src_exports, {
39
40
  module.exports = __toCommonJS(src_exports);
40
41
 
41
42
  // src/components/BalanceSheet/BalanceSheet.tsx
42
- var import_react5 = __toESM(require("react"));
43
+ var import_react6 = __toESM(require("react"));
43
44
 
44
45
  // src/api/util.ts
45
46
  var formStringFromObject = (object) => Object.entries(object).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(v)}`).join("&");
@@ -207,23 +208,82 @@ var balance_sheet_default = {
207
208
  // src/api/layer/balance_sheet.ts
208
209
  var getBalanceSheet = (_token, _params) => () => balance_sheet_default;
209
210
 
211
+ // src/models/APIError.ts
212
+ var APIError = class _APIError extends Error {
213
+ constructor(message, code, messages) {
214
+ super(message);
215
+ this.name = "APIError";
216
+ this.code = code;
217
+ this.messages = messages;
218
+ Object.setPrototypeOf(this, _APIError.prototype);
219
+ }
220
+ getMessage() {
221
+ return this.message;
222
+ }
223
+ getAllMessages() {
224
+ return this.messages?.map((x) => x.description);
225
+ }
226
+ };
227
+
210
228
  // src/api/layer/authenticated_http.ts
211
- var get = (url) => (accessToken, options) => () => fetch(url(options?.params || {}), {
229
+ var get = (url) => (baseUrl, accessToken, options) => () => fetch(`${baseUrl}${url(options?.params || {})}`, {
212
230
  headers: {
213
231
  Authorization: "Bearer " + (accessToken || ""),
214
232
  "Content-Type": "application/json"
215
233
  },
216
234
  method: "GET"
217
- }).then((res) => res.json());
218
- var put = (url) => (accessToken, options) => fetch(url(options?.params || {}), {
235
+ }).then((res) => handleResponse(res)).catch((error) => handleException(error));
236
+ var request = (verb) => (url) => (baseUrl, accessToken, options) => fetch(`${baseUrl}${url(options?.params || {})}`, {
219
237
  headers: {
220
238
  Authorization: "Bearer " + (accessToken || ""),
221
239
  "Content-Type": "application/json",
222
240
  "Cache-Control": "no-cache"
223
241
  },
224
- method: "PUT",
242
+ method: verb.toUpperCase(),
225
243
  body: JSON.stringify(options?.body)
226
- }).then((res) => res.json());
244
+ }).then((res) => handleResponse(res)).catch((error) => handleException(error));
245
+ var post = request("post");
246
+ var put = request("put");
247
+ var handleResponse = async (res) => {
248
+ if (!res.ok) {
249
+ const errors = await tryToReadErrorsFromResponse(res);
250
+ const apiError = new APIError(
251
+ "An error occurred while fetching the data from API.",
252
+ res.status,
253
+ errors
254
+ );
255
+ throw apiError;
256
+ }
257
+ const parsedResponse = await res.json();
258
+ if (parsedResponse && "errors" in parsedResponse) {
259
+ const apiError = new APIError(
260
+ "Errors in the API response.",
261
+ res.status,
262
+ parsedResponse.errors ?? []
263
+ );
264
+ throw apiError;
265
+ }
266
+ return parsedResponse;
267
+ };
268
+ var handleException = async (error) => {
269
+ if (error.name === "APIError") {
270
+ throw error;
271
+ }
272
+ const apiError = new APIError(
273
+ "An error occurred while parsing the data from API.",
274
+ void 0,
275
+ []
276
+ );
277
+ throw apiError;
278
+ };
279
+ var tryToReadErrorsFromResponse = async (res) => {
280
+ try {
281
+ const data = await res?.json();
282
+ return data?.errors ?? [];
283
+ } catch (_err) {
284
+ return [];
285
+ }
286
+ };
227
287
 
228
288
  // src/api/layer/bankTransactions.ts
229
289
  var getBankTransactions = get(
@@ -231,29 +291,37 @@ var getBankTransactions = get(
231
291
  businessId,
232
292
  sortBy = "date",
233
293
  sortOrder = "DESC"
234
- }) => `https://sandbox.layerfi.com/v1/businesses/${businessId}/bank-transactions?sort_by=${sortBy}&sort_order=${sortOrder}`
294
+ }) => `/v1/businesses/${businessId}/bank-transactions?sort_by=${sortBy}&sort_order=${sortOrder}`
235
295
  );
236
296
  var categorizeBankTransaction = put(
237
- ({ businessId, bankTransactionId }) => `https://sandbox.layerfi.com/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/categorize`
297
+ ({ businessId, bankTransactionId }) => `/v1/businesses/${businessId}/bank-transactions/${bankTransactionId}/categorize`
238
298
  );
239
299
 
240
300
  // src/api/layer/categories.ts
241
- var getCategories = get(
242
- ({ businessId }) => `https://sandbox.layerfi.com/v1/businesses/${businessId}/categories`
301
+ var getCategories = get(({ businessId }) => `/v1/businesses/${businessId}/categories`);
302
+
303
+ // src/api/layer/chart_of_accounts.ts
304
+ var getChartOfAccounts = get(
305
+ ({ businessId }) => `/v1/businesses/${businessId}/ledger/accounts`
306
+ );
307
+ var createAccount = post(
308
+ ({ businessId }) => `/v1/businesses/${businessId}/ledger/accounts`
243
309
  );
244
310
 
245
311
  // src/api/layer/profit_and_loss.ts
246
312
  var getProfitAndLoss = get(
247
- ({ businessId, startDate, endDate }) => `https://sandbox.layerfi.com/v1/businesses/${businessId}/reports/profit-and-loss?start_date=${startDate}&end_date=${endDate}`
313
+ ({ businessId, startDate, endDate }) => `/v1/businesses/${businessId}/reports/profit-and-loss?start_date=${startDate ? encodeURIComponent(startDate) : ""}&end_date=${endDate ? encodeURIComponent(endDate) : ""}`
248
314
  );
249
315
 
250
316
  // src/api/layer.ts
251
317
  var Layer = {
252
318
  authenticate,
253
319
  categorizeBankTransaction,
320
+ createAccount,
254
321
  getBalanceSheet,
255
322
  getBankTransactions,
256
323
  getCategories,
324
+ getChartOfAccounts,
257
325
  getProfitAndLoss
258
326
  };
259
327
 
@@ -263,9 +331,17 @@ var import_react2 = require("react");
263
331
  // src/contexts/LayerContext/LayerContext.tsx
264
332
  var import_react = require("react");
265
333
  var LayerContext = (0, import_react.createContext)({
266
- auth: { access_token: "", expires_in: -1, token_type: "" },
334
+ auth: {
335
+ access_token: "",
336
+ expires_at: new Date(2e3, 1, 1),
337
+ expires_in: -1,
338
+ token_type: ""
339
+ },
267
340
  businessId: "",
268
- categories: []
341
+ categories: [],
342
+ apiUrl: "",
343
+ theme: void 0,
344
+ setTheme: () => void 0
269
345
  });
270
346
 
271
347
  // src/hooks/useLayerContext/useLayerContext.tsx
@@ -274,7 +350,7 @@ var useLayerContext = () => (0, import_react2.useContext)(LayerContext);
274
350
  // src/hooks/useBalanceSheet/useBalanceSheet.tsx
275
351
  var import_date_fns = require("date-fns");
276
352
  var import_swr = __toESM(require("swr"));
277
- var useBalanceSheet = (date) => {
353
+ var useBalanceSheet = (date = /* @__PURE__ */ new Date()) => {
278
354
  const { auth, businessId } = useLayerContext();
279
355
  const dateString = (0, import_date_fns.format)((0, import_date_fns.startOfDay)(date), "yyyy-mm-dd");
280
356
  const { data, isLoading, error } = (0, import_swr.default)(
@@ -358,67 +434,44 @@ var import_react4 = __toESM(require("react"));
358
434
 
359
435
  // src/icons/ChevronDown.tsx
360
436
  var React4 = __toESM(require("react"));
361
- var ChevronDown = ({ size = 24, ...props }) => /* @__PURE__ */ React4.createElement(
437
+ var ChevronDown = ({ size = 18, ...props }) => /* @__PURE__ */ React4.createElement(
362
438
  "svg",
363
439
  {
440
+ viewBox: "0 0 18 18",
441
+ fill: "none",
364
442
  xmlns: "http://www.w3.org/2000/svg",
443
+ ...props,
365
444
  width: size,
366
- height: size,
367
- fill: "none",
368
- viewBox: "0 0 24 24",
369
- ...props
445
+ height: size
370
446
  },
371
447
  /* @__PURE__ */ React4.createElement(
372
448
  "path",
373
449
  {
450
+ d: "M4.5 6.75L9 11.25L13.5 6.75",
451
+ stroke: "currentColor",
374
452
  strokeLinecap: "round",
375
- strokeLinejoin: "round",
376
- strokeWidth: 2,
377
- d: "m6 9 6 6 6-6"
453
+ strokeLinejoin: "round"
378
454
  }
379
455
  )
380
456
  );
381
457
  var ChevronDown_default = ChevronDown;
382
458
 
383
- // src/icons/ChevronRight.tsx
384
- var React5 = __toESM(require("react"));
385
- var ChavronRight = ({ strokeColor, size, ...props }) => /* @__PURE__ */ React5.createElement(
386
- "svg",
387
- {
388
- xmlns: "http://www.w3.org/2000/svg",
389
- width: size || 24,
390
- height: size || 24,
391
- fill: "none",
392
- viewBox: "0 0 24 24",
393
- ...props
394
- },
395
- /* @__PURE__ */ React5.createElement(
396
- "path",
397
- {
398
- stroke: strokeColor ?? "#000",
399
- strokeLinecap: "round",
400
- strokeLinejoin: "round",
401
- strokeWidth: 2,
402
- d: "m9 18 6-6-6-6"
403
- }
404
- )
405
- );
406
- var ChevronRight_default = ChavronRight;
407
-
408
459
  // src/models/Money.ts
409
460
  var formatter = new Intl.NumberFormat("en-US", {
410
461
  minimumIntegerDigits: 1,
411
462
  minimumFractionDigits: 2,
412
463
  maximumFractionDigits: 2
413
464
  });
414
- var centsToDollars = (cents) => formatter.format(cents / 100);
415
- var dollarsToCents = (dollars) => Math.round(parseFloat(dollars) * 100);
465
+ var centsToDollars = (cents = NaN) => isNaN(cents) ? "-.--" : formatter.format(cents / 100);
466
+ var dollarsToCents = (dollars = "") => Math.round(parseFloat(dollars) * 100);
416
467
 
417
468
  // src/components/BalanceSheetRow/BalanceSheetRow.tsx
418
469
  var BalanceSheetRow = ({
419
470
  lineItem,
420
471
  depth = 0,
421
- maxDepth = 2
472
+ maxDepth = 2,
473
+ variant,
474
+ summarize = true
422
475
  }) => {
423
476
  if (!lineItem) {
424
477
  return null;
@@ -441,9 +494,11 @@ var BalanceSheetRow = ({
441
494
  );
442
495
  labelClasses.push(`Layer__balance-sheet-row__label--depth-${depth}`);
443
496
  valueClasses.push(`Layer__balance-sheet-row__value--depth-${depth}`);
497
+ variant && labelClasses.push(`Layer__balance-sheet-row__label--variant-${variant}`);
498
+ variant && valueClasses.push(`Layer__balance-sheet-row__value--variant-${variant}`);
444
499
  const toggleExpanded = () => setExpanded(!expanded);
445
500
  const canGoDeeper = depth < maxDepth;
446
- const hasChildren = line_items?.length > 0;
501
+ const hasChildren = (line_items?.length ?? 0) > 0;
447
502
  const displayChildren = hasChildren && canGoDeeper;
448
503
  labelClasses.push(
449
504
  `Layer__balance-sheet-row__label--display-children-${displayChildren}`
@@ -451,21 +506,68 @@ var BalanceSheetRow = ({
451
506
  valueClasses.push(
452
507
  `Layer__balance-sheet-row__value--display-children-${displayChildren}`
453
508
  );
454
- return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement("div", { className: labelClasses.join(" "), onClick: toggleExpanded }, expanded ? /* @__PURE__ */ import_react4.default.createElement(ChevronDown_default, { size: 16 }) : /* @__PURE__ */ import_react4.default.createElement(ChevronRight_default, { size: 16 }), display_name), /* @__PURE__ */ import_react4.default.createElement("div", { className: valueClasses.join(" ") }, !!value && amountString), canGoDeeper && hasChildren && expanded && (line_items || []).map((line_item) => /* @__PURE__ */ import_react4.default.createElement(
455
- BalanceSheetRow,
509
+ displayChildren && expanded && labelClasses.push("Layer__balance-sheet-row__label--expanded");
510
+ displayChildren && expanded && valueClasses.push("Layer__balance-sheet-row__value--expanded");
511
+ return /* @__PURE__ */ import_react4.default.createElement(import_react4.default.Fragment, null, /* @__PURE__ */ import_react4.default.createElement("div", { className: labelClasses.join(" "), onClick: toggleExpanded }, /* @__PURE__ */ import_react4.default.createElement(ChevronDown_default, { size: 16 }), display_name), /* @__PURE__ */ import_react4.default.createElement("div", { className: valueClasses.join(" ") }, !!value && amountString), canGoDeeper && hasChildren && /* @__PURE__ */ import_react4.default.createElement(
512
+ "div",
456
513
  {
457
- key: line_item.display_name,
458
- lineItem: line_item,
459
- depth: depth + 1,
460
- maxDepth
461
- }
462
- )));
514
+ className: `Layer__balance-sheet-row__children ${expanded && "Layer__balance-sheet-row__children--expanded"}`
515
+ },
516
+ /* @__PURE__ */ import_react4.default.createElement("div", { className: "Layer__balance-sheet-row__children--content" }, (line_items || []).map((line_item, idx) => /* @__PURE__ */ import_react4.default.createElement(
517
+ BalanceSheetRow,
518
+ {
519
+ key: `${line_item.display_name}_${idx}`,
520
+ lineItem: line_item,
521
+ depth: depth + 1,
522
+ maxDepth
523
+ }
524
+ )), summarize && /* @__PURE__ */ import_react4.default.createElement(
525
+ BalanceSheetRow,
526
+ {
527
+ key: display_name,
528
+ lineItem: { value, display_name: `Total of ${display_name}` },
529
+ variant: "summation",
530
+ depth: depth + 1,
531
+ maxDepth
532
+ }
533
+ ))
534
+ ));
535
+ };
536
+
537
+ // src/components/SkeletonBalanceSheetRow/SkeletonBalanceSheetRow.tsx
538
+ var import_react5 = __toESM(require("react"));
539
+ var SkeletonBalanceSheetRow = ({ children }) => {
540
+ const labelClasses = [
541
+ "Layer__balance-sheet-row",
542
+ "Layer__balance-sheet-row__label",
543
+ "Layer__balance-sheet-row__label--skeleton"
544
+ ];
545
+ const valueClasses = [
546
+ "Layer__balance-sheet-row",
547
+ "Layer__balance-sheet-row__value",
548
+ "Layer__balance-sheet-row__value--skeleton"
549
+ ];
550
+ return /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("div", { className: labelClasses.join(" ") }, children && /* @__PURE__ */ import_react5.default.createElement(ChevronDown_default, { size: 16 }), /* @__PURE__ */ import_react5.default.createElement(
551
+ "div",
552
+ {
553
+ style: { width: "20rem" },
554
+ className: "Layer__balance-sheet-row__skeleton-text"
555
+ },
556
+ " "
557
+ )), /* @__PURE__ */ import_react5.default.createElement("div", { className: valueClasses.join(" ") }, /* @__PURE__ */ import_react5.default.createElement(
558
+ "div",
559
+ {
560
+ style: { width: "4rem" },
561
+ className: "Layer__balance-sheet-row__skeleton-text"
562
+ },
563
+ " "
564
+ )), children && /* @__PURE__ */ import_react5.default.createElement("div", { className: "Layer__balance-sheet-row__children Layer__balance-sheet-row__children--expanded Layer__balance-sheet-row__children--skeleton" }, children));
463
565
  };
464
566
 
465
567
  // src/components/BalanceSheet/BalanceSheet.tsx
466
568
  var import_date_fns3 = require("date-fns");
467
569
  var BalanceSheet = () => {
468
- const [effectiveDate, setEffectiveDate] = (0, import_react5.useState)(/* @__PURE__ */ new Date());
570
+ const [effectiveDate, setEffectiveDate] = (0, import_react6.useState)(/* @__PURE__ */ new Date());
469
571
  const { data, isLoading } = useBalanceSheet(effectiveDate);
470
572
  const assets = {
471
573
  name: "Assets",
@@ -480,22 +582,29 @@ var BalanceSheet = () => {
480
582
  value: void 0
481
583
  };
482
584
  const dateString = (0, import_date_fns3.format)(effectiveDate, "LLLL d, yyyy");
483
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: "Layer__balance-sheet" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "Layer__balance-sheet__header" }, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "Layer__balance-sheet__title" }, "Balance Sheet", /* @__PURE__ */ import_react5.default.createElement("span", { className: "Layer__balance-sheet__date" }, dateString)), /* @__PURE__ */ import_react5.default.createElement(
585
+ return /* @__PURE__ */ import_react6.default.createElement("div", { className: "Layer__component Layer__balance-sheet" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "Layer__balance-sheet__header" }, /* @__PURE__ */ import_react6.default.createElement("h2", { className: "Layer__balance-sheet__title" }, "Balance Sheet", /* @__PURE__ */ import_react6.default.createElement("span", { className: "Layer__balance-sheet__date" }, dateString)), /* @__PURE__ */ import_react6.default.createElement(
484
586
  BalanceSheetDatePicker,
485
587
  {
486
588
  value: effectiveDate,
487
589
  onChange: (event) => setEffectiveDate((0, import_date_fns3.parseISO)(event.target.value))
488
590
  }
489
- ), /* @__PURE__ */ import_react5.default.createElement("button", { className: "Layer__balance-sheet__download-button" }, /* @__PURE__ */ import_react5.default.createElement(DownloadCloud_default, null), "Download")), !data || isLoading ? /* @__PURE__ */ import_react5.default.createElement("div", null, "Loading") : /* @__PURE__ */ import_react5.default.createElement("div", { className: "Layer__balance-sheet__table" }, /* @__PURE__ */ import_react5.default.createElement(BalanceSheetRow, { key: assets.name, lineItem: assets }), /* @__PURE__ */ import_react5.default.createElement(BalanceSheetRow, { key: lne.name, lineItem: lne })));
591
+ ), /* @__PURE__ */ import_react6.default.createElement("button", { className: "Layer__balance-sheet__download-button" }, /* @__PURE__ */ import_react6.default.createElement(DownloadCloud_default, null), "Download")), !data || isLoading ? /* @__PURE__ */ import_react6.default.createElement("div", { className: "Layer__balance-sheet__table" }, /* @__PURE__ */ import_react6.default.createElement(SkeletonBalanceSheetRow, null, /* @__PURE__ */ import_react6.default.createElement(SkeletonBalanceSheetRow, null), /* @__PURE__ */ import_react6.default.createElement(SkeletonBalanceSheetRow, null, /* @__PURE__ */ import_react6.default.createElement(SkeletonBalanceSheetRow, null), /* @__PURE__ */ import_react6.default.createElement(SkeletonBalanceSheetRow, null))), /* @__PURE__ */ import_react6.default.createElement(SkeletonBalanceSheetRow, null, /* @__PURE__ */ import_react6.default.createElement(SkeletonBalanceSheetRow, null))) : /* @__PURE__ */ import_react6.default.createElement("div", { className: "Layer__balance-sheet__table" }, /* @__PURE__ */ import_react6.default.createElement(
592
+ BalanceSheetRow,
593
+ {
594
+ key: assets.name,
595
+ lineItem: assets,
596
+ summarize: false
597
+ }
598
+ ), /* @__PURE__ */ import_react6.default.createElement(BalanceSheetRow, { key: lne.name, lineItem: lne, summarize: false })));
490
599
  };
491
600
 
492
601
  // src/components/BankTransactions/BankTransactions.tsx
493
- var import_react12 = __toESM(require("react"));
602
+ var import_react29 = __toESM(require("react"));
494
603
 
495
604
  // src/hooks/useBankTransactions/useBankTransactions.tsx
496
605
  var import_swr2 = __toESM(require("swr"));
497
606
  var useBankTransactions = () => {
498
- const { auth, businessId } = useLayerContext();
607
+ const { auth, businessId, apiUrl } = useLayerContext();
499
608
  const {
500
609
  data: responseData,
501
610
  isLoading,
@@ -503,437 +612,1333 @@ var useBankTransactions = () => {
503
612
  mutate
504
613
  } = (0, import_swr2.default)(
505
614
  businessId && auth?.access_token && `bank-transactions-${businessId}`,
506
- Layer.getBankTransactions(auth?.access_token, { params: { businessId } })
615
+ Layer.getBankTransactions(apiUrl, auth?.access_token, {
616
+ params: { businessId }
617
+ })
507
618
  );
508
619
  const {
509
620
  data = [],
510
621
  meta: metadata = {},
511
622
  error = void 0
512
623
  } = responseData || {};
513
- const categorize = (id, newCategory) => Layer.categorizeBankTransaction(auth.access_token, {
514
- params: { businessId, bankTransactionId: id },
515
- body: newCategory
516
- }).then(({ data: transaction, error: error2 }) => {
517
- if (transaction) {
518
- mutate();
624
+ const categorize = (id, newCategory) => {
625
+ const foundBT = data.find((x) => x.business_id === businessId && x.id === id);
626
+ if (foundBT) {
627
+ updateOneLocal({ ...foundBT, processing: true, error: void 0 });
519
628
  }
520
- if (error2) {
521
- console.error(error2);
522
- throw error2;
629
+ return Layer.categorizeBankTransaction(apiUrl, auth.access_token, {
630
+ params: { businessId, bankTransactionId: id },
631
+ body: newCategory
632
+ }).then(({ data: newBT, errors }) => {
633
+ if (newBT) {
634
+ newBT.recently_categorized = true;
635
+ updateOneLocal(newBT);
636
+ }
637
+ if (errors) {
638
+ console.error(errors);
639
+ throw errors;
640
+ }
641
+ }).catch((err) => {
642
+ const newBT = data.find(
643
+ (x) => x.business_id === businessId && x.id === id
644
+ );
645
+ if (newBT) {
646
+ updateOneLocal({
647
+ ...newBT,
648
+ error: err.message,
649
+ processing: false
650
+ });
651
+ }
652
+ });
653
+ };
654
+ const updateOneLocal = (newBankTransaction) => {
655
+ const updatedData = data.map(
656
+ (bt) => bt.id === newBankTransaction.id ? newBankTransaction : bt
657
+ );
658
+ mutate({ data: updatedData }, { revalidate: false });
659
+ };
660
+ return {
661
+ data,
662
+ metadata,
663
+ isLoading,
664
+ error: responseError || error,
665
+ categorize,
666
+ updateOneLocal
667
+ };
668
+ };
669
+
670
+ // src/hooks/useElementSize/useElementSize.ts
671
+ var import_react7 = require("react");
672
+ var useElementSize = (callback) => {
673
+ const ref = (0, import_react7.useRef)(null);
674
+ (0, import_react7.useLayoutEffect)(() => {
675
+ const element = ref?.current;
676
+ if (!element) {
677
+ return;
523
678
  }
524
- });
525
- return { data, metadata, isLoading, error, categorize };
679
+ const observer = new ResizeObserver((entries) => {
680
+ callback(element, entries[0], {
681
+ width: element.offsetWidth,
682
+ height: element.offsetHeight
683
+ });
684
+ });
685
+ observer.observe(element);
686
+ return () => {
687
+ observer.disconnect();
688
+ };
689
+ }, [callback, ref]);
690
+ return ref;
526
691
  };
527
692
 
528
- // src/components/BankTransactionRow/BankTransactionRow.tsx
529
- var import_react11 = __toESM(require("react"));
693
+ // src/components/BankTransactionListItem/BankTransactionListItem.tsx
694
+ var import_react24 = __toESM(require("react"));
530
695
 
531
- // src/icons/CheckedCircle.tsx
532
- var React8 = __toESM(require("react"));
533
- var CheckedCircle = ({
534
- fillColor = "none",
535
- strokeColor = "#000",
536
- size = 24,
696
+ // src/components/Button/Button.tsx
697
+ var import_react8 = __toESM(require("react"));
698
+ var import_classnames = __toESM(require("classnames"));
699
+ var Button = ({
700
+ className,
701
+ children,
702
+ variant = "primary" /* primary */,
703
+ leftIcon,
704
+ rightIcon,
705
+ iconOnly,
537
706
  ...props
538
- }) => /* @__PURE__ */ React8.createElement(
707
+ }) => {
708
+ let justify = "center";
709
+ if (leftIcon && rightIcon) {
710
+ justify = "space-between";
711
+ } else if (rightIcon) {
712
+ justify = "space-between";
713
+ } else if (leftIcon) {
714
+ justify = "start";
715
+ }
716
+ const baseClassName = (0, import_classnames.default)(
717
+ "Layer__btn",
718
+ `Layer__btn--${variant}`,
719
+ iconOnly ? "Layer__btn--icon-only" : "",
720
+ className
721
+ );
722
+ return /* @__PURE__ */ import_react8.default.createElement("button", { ...props, className: baseClassName }, /* @__PURE__ */ import_react8.default.createElement("span", { className: `Layer__btn-content Layer__justify--${justify}` }, leftIcon && /* @__PURE__ */ import_react8.default.createElement("span", { className: "Layer__btn-icon Layer__btn-icon--left" }, leftIcon), !iconOnly && /* @__PURE__ */ import_react8.default.createElement("span", { className: "Layer__btn-text" }, children), rightIcon && /* @__PURE__ */ import_react8.default.createElement("span", { className: "Layer__btn-icon Layer__btn-icon--right" }, rightIcon)));
723
+ };
724
+
725
+ // src/components/Button/SubmitButton.tsx
726
+ var import_react13 = __toESM(require("react"));
727
+
728
+ // src/icons/AlertCircle.tsx
729
+ var React9 = __toESM(require("react"));
730
+ var AlertCircle = ({ size = 18, ...props }) => /* @__PURE__ */ React9.createElement(
539
731
  "svg",
540
732
  {
733
+ viewBox: "0 0 18 18",
734
+ fill: "none",
541
735
  xmlns: "http://www.w3.org/2000/svg",
736
+ ...props,
542
737
  width: size,
543
- height: size,
544
- viewBox: "0 0 24 24",
545
- fill: fillColor,
546
- ...props
738
+ height: size
547
739
  },
548
- /* @__PURE__ */ React8.createElement(
740
+ /* @__PURE__ */ React9.createElement(
549
741
  "path",
550
742
  {
551
- stroke: strokeColor,
743
+ d: "M9 16.5C13.1421 16.5 16.5 13.1421 16.5 9C16.5 4.85786 13.1421 1.5 9 1.5C4.85786 1.5 1.5 4.85786 1.5 9C1.5 13.1421 4.85786 16.5 9 16.5Z",
744
+ stroke: "currentColor",
552
745
  strokeLinecap: "round",
553
- strokeLinejoin: "round",
554
- strokeWidth: 2,
555
- d: "m7.5 12 3 3 6-6m5.5 3c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10Z"
746
+ strokeLinejoin: "round"
747
+ }
748
+ ),
749
+ /* @__PURE__ */ React9.createElement(
750
+ "path",
751
+ {
752
+ d: "M9 6V9",
753
+ stroke: "currentColor",
754
+ strokeLinecap: "round",
755
+ strokeLinejoin: "round"
756
+ }
757
+ ),
758
+ /* @__PURE__ */ React9.createElement(
759
+ "path",
760
+ {
761
+ d: "M9 12H9.0075",
762
+ stroke: "currentColor",
763
+ strokeLinecap: "round",
764
+ strokeLinejoin: "round"
556
765
  }
557
766
  )
558
767
  );
559
- var CheckedCircle_default = CheckedCircle;
768
+ var AlertCircle_default = AlertCircle;
560
769
 
561
- // src/icons/ChevronUp.tsx
562
- var React9 = __toESM(require("react"));
563
- var ChevronUp = (props) => /* @__PURE__ */ React9.createElement(
770
+ // src/icons/Check.tsx
771
+ var React10 = __toESM(require("react"));
772
+ var Check = ({ size = 18, ...props }) => /* @__PURE__ */ React10.createElement(
564
773
  "svg",
565
774
  {
566
- xmlns: "http://www.w3.org/2000/svg",
567
- width: 24,
568
- height: 24,
775
+ viewBox: "0 0 18 18",
569
776
  fill: "none",
570
- viewBox: "0 0 24 24",
571
- ...props
777
+ xmlns: "http://www.w3.org/2000/svg",
778
+ ...props,
779
+ width: size,
780
+ height: size
572
781
  },
573
- /* @__PURE__ */ React9.createElement(
782
+ /* @__PURE__ */ React10.createElement(
574
783
  "path",
575
784
  {
576
- stroke: "#000",
785
+ d: "M15 4.5L6.75 12.75L3 9",
786
+ stroke: "currentColor",
577
787
  strokeLinecap: "round",
578
- strokeLinejoin: "round",
579
- strokeWidth: 2,
580
- d: "m18 15-6-6-6 6"
788
+ strokeLinejoin: "round"
581
789
  }
582
790
  )
583
791
  );
584
- var ChevronUp_default = ChevronUp;
585
-
586
- // src/components/CategoryMenu/CategoryMenu.tsx
587
- var import_react6 = __toESM(require("react"));
588
- var import_react_select = __toESM(require("react-select"));
589
- var CategoryMenu = ({
590
- bankTransaction,
591
- name,
592
- value,
593
- onChange
594
- }) => {
595
- const { categories } = useLayerContext();
596
- const suggestedOptions = bankTransaction?.categorization_flow?.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ ? [
597
- {
598
- label: "Suggested",
599
- options: bankTransaction.categorization_flow.suggestions
600
- }
601
- ] : [];
602
- const categoryOptions = (categories || []).map((category) => {
603
- if (category?.subCategories && category?.subCategories?.length > 0) {
604
- return {
605
- label: category.display_name,
606
- options: category.subCategories
607
- };
608
- }
609
- return {
610
- label: category.display_name,
611
- options: [category]
612
- };
613
- }).filter((x) => x);
614
- const options = [...suggestedOptions, ...categoryOptions];
615
- return /* @__PURE__ */ import_react6.default.createElement(
616
- import_react_select.default,
617
- {
618
- name,
619
- className: "Layer__category-menu",
620
- options,
621
- isSearchable: true,
622
- value,
623
- onChange: (newValue) => newValue && onChange(newValue),
624
- getOptionLabel: (category) => category.display_name,
625
- getOptionValue: (category) => category.stable_name || category.category,
626
- menuPortalTarget: document.body,
627
- styles: { menuPortal: (base) => ({ ...base, zIndex: 9999 }) }
628
- }
629
- );
630
- };
631
-
632
- // src/components/ExpandedBankTransactionRow/ExpandedBankTransactionRow.tsx
633
- var import_react9 = __toESM(require("react"));
792
+ var Check_default = Check;
634
793
 
635
- // src/icons/Link.tsx
794
+ // src/icons/CheckCircle.tsx
636
795
  var React11 = __toESM(require("react"));
637
- var Link = ({ size = 24, ...props }) => /* @__PURE__ */ React11.createElement(
796
+ var CheckCircle = ({ size = 18, ...props }) => /* @__PURE__ */ React11.createElement(
638
797
  "svg",
639
798
  {
799
+ viewBox: "0 0 18 18",
800
+ fill: "none",
640
801
  xmlns: "http://www.w3.org/2000/svg",
802
+ ...props,
641
803
  width: size,
642
- height: size,
643
- fill: "none",
644
- viewBox: "0 0 24 24",
645
- ...props
804
+ height: size
646
805
  },
647
806
  /* @__PURE__ */ React11.createElement(
648
807
  "path",
649
808
  {
650
- stroke: "#000",
809
+ d: "M16.5 8.30999V8.99999C16.4991 10.6173 15.9754 12.191 15.007 13.4864C14.0386 14.7817 12.6775 15.7293 11.1265 16.1879C9.57557 16.6465 7.91794 16.5914 6.40085 16.0309C4.88375 15.4704 3.58848 14.4346 2.70821 13.0778C1.82794 11.721 1.40984 10.116 1.51625 8.50223C1.62266 6.88841 2.2479 5.35223 3.2987 4.12279C4.34951 2.89335 5.76958 2.03653 7.34713 1.6801C8.92469 1.32367 10.5752 1.48674 12.0525 2.14499",
810
+ stroke: "currentColor",
651
811
  strokeLinecap: "round",
652
- strokeLinejoin: "round",
653
- strokeWidth: 2,
654
- d: "m12.708 18.364-1.415 1.414a5 5 0 1 1-7.07-7.07l1.413-1.415m12.728 1.414 1.415-1.414a5 5 0 0 0-7.071-7.071l-1.415 1.414M8.5 15.5l7-7"
812
+ strokeLinejoin: "round"
813
+ }
814
+ ),
815
+ /* @__PURE__ */ React11.createElement(
816
+ "path",
817
+ {
818
+ d: "M16.5 3L9 10.5075L6.75 8.2575",
819
+ stroke: "currentColor",
820
+ strokeLinecap: "round",
821
+ strokeLinejoin: "round"
655
822
  }
656
823
  )
657
824
  );
658
- var Link_default = Link;
825
+ var CheckCircle_default = CheckCircle;
659
826
 
660
- // src/icons/LinkBroken.tsx
827
+ // src/icons/Loader.tsx
661
828
  var React12 = __toESM(require("react"));
662
- var LinkBroken = ({ size = 24, ...props }) => /* @__PURE__ */ React12.createElement(
829
+ var Loader = ({ size = 18, ...props }) => /* @__PURE__ */ React12.createElement(
663
830
  "svg",
664
831
  {
832
+ viewBox: "0 0 18 18",
833
+ fill: "none",
665
834
  xmlns: "http://www.w3.org/2000/svg",
835
+ ...props,
666
836
  width: size,
667
- height: size,
668
- fill: "none",
669
- viewBox: "0 0 24 24",
670
- ...props
837
+ height: size
671
838
  },
672
839
  /* @__PURE__ */ React12.createElement(
673
840
  "path",
674
841
  {
675
- stroke: "#000",
842
+ d: "M9 1.5V4.5",
843
+ stroke: "currentColor",
676
844
  strokeLinecap: "round",
677
- strokeLinejoin: "round",
678
- strokeWidth: 2,
679
- d: "m8.5 15.5 7-7M9 4V2m6 18v2M4 9H2m18 6h2M4.914 4.914 3.5 3.5m15.586 15.586L20.5 20.5M12 17.657l-2.121 2.121a4 4 0 1 1-5.657-5.657L6.343 12m11.314 0 2.121-2.121a4 4 0 0 0-5.657-5.657L12 6.343"
845
+ strokeLinejoin: "round"
846
+ }
847
+ ),
848
+ /* @__PURE__ */ React12.createElement(
849
+ "path",
850
+ {
851
+ d: "M9 13.5V16.5",
852
+ stroke: "currentColor",
853
+ strokeLinecap: "round",
854
+ strokeLinejoin: "round"
855
+ }
856
+ ),
857
+ /* @__PURE__ */ React12.createElement(
858
+ "path",
859
+ {
860
+ d: "M3.6975 3.6975L5.82 5.82",
861
+ stroke: "currentColor",
862
+ strokeLinecap: "round",
863
+ strokeLinejoin: "round"
864
+ }
865
+ ),
866
+ /* @__PURE__ */ React12.createElement(
867
+ "path",
868
+ {
869
+ d: "M12.18 12.18L14.3025 14.3025",
870
+ stroke: "currentColor",
871
+ strokeLinecap: "round",
872
+ strokeLinejoin: "round"
873
+ }
874
+ ),
875
+ /* @__PURE__ */ React12.createElement(
876
+ "path",
877
+ {
878
+ d: "M1.5 9H4.5",
879
+ stroke: "currentColor",
880
+ strokeLinecap: "round",
881
+ strokeLinejoin: "round"
882
+ }
883
+ ),
884
+ /* @__PURE__ */ React12.createElement(
885
+ "path",
886
+ {
887
+ d: "M13.5 9H16.5",
888
+ stroke: "currentColor",
889
+ strokeLinecap: "round",
890
+ strokeLinejoin: "round"
891
+ }
892
+ ),
893
+ /* @__PURE__ */ React12.createElement(
894
+ "path",
895
+ {
896
+ d: "M3.6975 14.3025L5.82 12.18",
897
+ stroke: "currentColor",
898
+ strokeLinecap: "round",
899
+ strokeLinejoin: "round"
900
+ }
901
+ ),
902
+ /* @__PURE__ */ React12.createElement(
903
+ "path",
904
+ {
905
+ d: "M12.18 5.82L14.3025 3.6975",
906
+ stroke: "currentColor",
907
+ strokeLinecap: "round",
908
+ strokeLinejoin: "round"
680
909
  }
681
910
  )
682
911
  );
683
- var LinkBroken_default = LinkBroken;
912
+ var Loader_default = Loader;
684
913
 
685
- // src/components/RadioButtonGroup/RadioButtonGroup.tsx
686
- var import_react8 = __toESM(require("react"));
914
+ // src/components/Tooltip/Tooltip.tsx
915
+ var import_react11 = __toESM(require("react"));
687
916
 
688
- // src/components/RadioButtonGroup/RadioButton.tsx
689
- var import_react7 = __toESM(require("react"));
690
- var RadioButton = ({
691
- checked,
692
- label,
693
- name,
694
- onChange,
695
- value,
917
+ // src/components/Tooltip/useTooltip.ts
918
+ var import_react9 = __toESM(require("react"));
919
+ var import_react10 = require("@floating-ui/react");
920
+ var TooltipContext = import_react9.default.createContext(null);
921
+ var useTooltipContext = () => {
922
+ const context = import_react9.default.useContext(TooltipContext);
923
+ if (context == null) {
924
+ throw new Error("Tooltip components must be wrapped in <Tooltip />");
925
+ }
926
+ return context;
927
+ };
928
+ var useTooltip = ({
929
+ initialOpen = false,
930
+ placement = "top",
931
+ open: controlledOpen,
932
+ onOpenChange: setControlledOpen,
696
933
  disabled,
697
- size
698
- }) => {
699
- return /* @__PURE__ */ import_react7.default.createElement(
700
- "label",
701
- {
702
- className: `Layer__radio-button-group__radio-button Layer__radio-button-group__radio-button--size-${size}`
934
+ offset: offsetProp = 5,
935
+ shift: shiftProp = { padding: 5 }
936
+ } = {}) => {
937
+ const [uncontrolledOpen, setUncontrolledOpen] = (0, import_react9.useState)(initialOpen);
938
+ const open = controlledOpen ?? uncontrolledOpen;
939
+ const setOpen = setControlledOpen ?? setUncontrolledOpen;
940
+ const data = (0, import_react10.useFloating)({
941
+ placement,
942
+ open: disabled ? false : open,
943
+ onOpenChange: setOpen,
944
+ whileElementsMounted: import_react10.autoUpdate,
945
+ middleware: [
946
+ (0, import_react10.offset)(offsetProp),
947
+ (0, import_react10.flip)({
948
+ crossAxis: placement.includes("-"),
949
+ fallbackAxisSideDirection: "start",
950
+ padding: shiftProp?.padding ?? 5
951
+ }),
952
+ (0, import_react10.shift)(shiftProp)
953
+ ]
954
+ });
955
+ const context = data.context;
956
+ const hover = (0, import_react10.useHover)(context, {
957
+ move: false,
958
+ enabled: controlledOpen == null
959
+ });
960
+ const focus = (0, import_react10.useFocus)(context, {
961
+ enabled: controlledOpen == null
962
+ });
963
+ const dismiss = (0, import_react10.useDismiss)(context);
964
+ const role = (0, import_react10.useRole)(context, { role: "tooltip" });
965
+ const interactions = (0, import_react10.useInteractions)([hover, focus, dismiss, role]);
966
+ const { isMounted, styles } = (0, import_react10.useTransitionStyles)(context, {
967
+ initial: {
968
+ opacity: 0
703
969
  },
704
- /* @__PURE__ */ import_react7.default.createElement(
705
- "input",
706
- {
707
- type: "radio",
708
- checked,
709
- name,
710
- onChange,
711
- value,
712
- disabled: disabled ?? false
713
- }
714
- ),
715
- /* @__PURE__ */ import_react7.default.createElement("div", null, label)
970
+ duration: 200
971
+ });
972
+ return import_react9.default.useMemo(
973
+ () => ({
974
+ open,
975
+ setOpen,
976
+ isMounted,
977
+ styles,
978
+ disabled,
979
+ ...interactions,
980
+ ...data
981
+ }),
982
+ [open, setOpen, interactions, data, styles, disabled]
716
983
  );
717
984
  };
718
985
 
719
- // src/components/RadioButtonGroup/RadioButtonGroup.tsx
720
- var RadioButtonGroup = ({
721
- name,
722
- size = "large",
723
- buttons,
724
- onChange,
725
- selected
986
+ // src/components/Tooltip/Tooltip.tsx
987
+ var import_react12 = require("@floating-ui/react");
988
+ var Tooltip = ({
989
+ children,
990
+ ...options
726
991
  }) => {
727
- const selectedValue = selected || buttons[0].value;
728
- return /* @__PURE__ */ import_react8.default.createElement(
992
+ const tooltip = useTooltip(options);
993
+ return /* @__PURE__ */ import_react11.default.createElement(TooltipContext.Provider, { value: tooltip }, children);
994
+ };
995
+ var TooltipTrigger = (0, import_react11.forwardRef)(function TooltipTrigger2({ children, asChild = false, ...props }, propRef) {
996
+ const context = useTooltipContext();
997
+ const childrenRef = children.ref;
998
+ const ref = (0, import_react12.useMergeRefs)([context.refs.setReference, propRef, childrenRef]);
999
+ if (asChild && (0, import_react11.isValidElement)(children)) {
1000
+ return (0, import_react11.cloneElement)(
1001
+ children,
1002
+ context.getReferenceProps({
1003
+ ref,
1004
+ ...props,
1005
+ ...children.props,
1006
+ "data-state": context.open ? "open" : "closed"
1007
+ })
1008
+ );
1009
+ }
1010
+ return /* @__PURE__ */ import_react11.default.createElement(
1011
+ "span",
1012
+ {
1013
+ ref,
1014
+ "data-state": context.open ? "open" : "closed",
1015
+ className: `Layer__tooltip-trigger Layer__tooltip-trigger--${context.open ? "open" : "closed"}`,
1016
+ ...context.getReferenceProps(props)
1017
+ },
1018
+ children
1019
+ );
1020
+ });
1021
+ var TooltipContent = (0, import_react11.forwardRef)(function TooltipContent2({ style, className, ...props }, propRef) {
1022
+ const context = useTooltipContext();
1023
+ const ref = (0, import_react12.useMergeRefs)([context.refs.setFloating, propRef]);
1024
+ if (!context.open || context.disabled)
1025
+ return null;
1026
+ return /* @__PURE__ */ import_react11.default.createElement(import_react12.FloatingPortal, null, /* @__PURE__ */ import_react11.default.createElement(
729
1027
  "div",
730
1028
  {
731
- className: `Layer__radio-button-group Layer__radio-button-group--size-${size}`
1029
+ ref,
1030
+ className,
1031
+ style: {
1032
+ ...context.styles,
1033
+ ...context.floatingStyles,
1034
+ ...style
1035
+ },
1036
+ ...context.getFloatingProps(props)
1037
+ }
1038
+ ));
1039
+ });
1040
+
1041
+ // src/components/Button/SubmitButton.tsx
1042
+ var import_classnames2 = __toESM(require("classnames"));
1043
+ var buildRightIcon = ({
1044
+ processing,
1045
+ error
1046
+ }) => {
1047
+ if (processing) {
1048
+ return /* @__PURE__ */ import_react13.default.createElement(Loader_default, { size: 14, className: "Layer__anim--rotating" });
1049
+ }
1050
+ if (error) {
1051
+ return /* @__PURE__ */ import_react13.default.createElement(Tooltip, { offset: 12 }, /* @__PURE__ */ import_react13.default.createElement(TooltipTrigger, null, /* @__PURE__ */ import_react13.default.createElement(AlertCircle_default, { size: 14 })), /* @__PURE__ */ import_react13.default.createElement(TooltipContent, { className: "Layer__tooltip" }, error));
1052
+ }
1053
+ return /* @__PURE__ */ import_react13.default.createElement("span", null, /* @__PURE__ */ import_react13.default.createElement(Check_default, { className: "Layer__btn-icon--on-active", size: 14 }), /* @__PURE__ */ import_react13.default.createElement(
1054
+ CheckCircle_default,
1055
+ {
1056
+ className: "Layer__btn-icon--on-inactive",
1057
+ size: 14,
1058
+ style: { paddingTop: 4 }
1059
+ }
1060
+ ));
1061
+ };
1062
+ var SubmitButton = ({
1063
+ active,
1064
+ className,
1065
+ processing,
1066
+ disabled,
1067
+ error,
1068
+ children,
1069
+ ...props
1070
+ }) => {
1071
+ const baseClassName = (0, import_classnames2.default)(
1072
+ active ? "Layer__btn--active" : "",
1073
+ className
1074
+ );
1075
+ return /* @__PURE__ */ import_react13.default.createElement(
1076
+ Button,
1077
+ {
1078
+ ...props,
1079
+ className: baseClassName,
1080
+ variant: "primary" /* primary */,
1081
+ disabled: processing || disabled,
1082
+ rightIcon: buildRightIcon({ processing, error })
732
1083
  },
733
- buttons.map((button) => /* @__PURE__ */ import_react8.default.createElement(
734
- RadioButton,
735
- {
736
- ...button,
737
- key: button.value,
738
- name,
739
- size,
740
- checked: selectedValue === button.value,
741
- onChange,
742
- disabled: button.disabled ?? false
743
- }
744
- ))
1084
+ children
745
1085
  );
746
1086
  };
747
1087
 
748
- // src/components/ExpandedBankTransactionRow/ExpandedBankTransactionRow.tsx
749
- var ExpandedBankTransactionRow = ({
1088
+ // src/components/CategoryMenu/CategoryMenu.tsx
1089
+ var import_react14 = __toESM(require("react"));
1090
+ var import_react_select = __toESM(require("react-select"));
1091
+ var DropdownIndicator = (props) => {
1092
+ return /* @__PURE__ */ import_react14.default.createElement(import_react_select.components.DropdownIndicator, { ...props }, /* @__PURE__ */ import_react14.default.createElement(ChevronDown_default, null));
1093
+ };
1094
+ var CategoryMenu = ({
750
1095
  bankTransaction,
751
- close
1096
+ name,
1097
+ value,
1098
+ onChange,
1099
+ disabled,
1100
+ className
752
1101
  }) => {
753
- const { categorize: categorizeBankTransaction2 } = useBankTransactions();
754
- const [purpose, setPurpose] = (0, import_react9.useState)("categorize" /* categorize */);
755
- const defaultCategory = bankTransaction.category || bankTransaction.categorization_flow?.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ && bankTransaction.categorization_flow?.suggestions?.[0];
756
- const [rowState, updateRowState] = (0, import_react9.useState)({
757
- splits: [
1102
+ const { categories } = useLayerContext();
1103
+ const suggestedOptions = bankTransaction?.categorization_flow?.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ ? [
1104
+ {
1105
+ label: "Suggested",
1106
+ options: bankTransaction.categorization_flow.suggestions
1107
+ }
1108
+ ] : [];
1109
+ const categoryOptions = (categories || []).map((category) => {
1110
+ if (category?.subCategories && category?.subCategories?.length > 0) {
1111
+ return {
1112
+ label: category.display_name,
1113
+ options: category.subCategories
1114
+ };
1115
+ }
1116
+ return {
1117
+ label: category.display_name,
1118
+ options: [category]
1119
+ };
1120
+ }).filter((x) => x);
1121
+ const options = [...suggestedOptions, ...categoryOptions];
1122
+ return /* @__PURE__ */ import_react14.default.createElement(
1123
+ import_react_select.default,
1124
+ {
1125
+ name,
1126
+ className: `Layer__category-menu Layer__select ${className ?? ""}`,
1127
+ classNamePrefix: "Layer__select",
1128
+ options,
1129
+ isSearchable: true,
1130
+ value,
1131
+ onChange: (newValue) => newValue && onChange(newValue),
1132
+ getOptionLabel: (category) => category.display_name,
1133
+ getOptionValue: (category) => category.stable_name || category.category,
1134
+ menuPortalTarget: document.body,
1135
+ styles: { menuPortal: (base) => ({ ...base, zIndex: 9999 }) },
1136
+ components: { DropdownIndicator },
1137
+ isDisabled: disabled
1138
+ }
1139
+ );
1140
+ };
1141
+
1142
+ // src/components/ExpandedBankTransactionRow/ExpandedBankTransactionRow.tsx
1143
+ var import_react22 = __toESM(require("react"));
1144
+
1145
+ // src/icons/FolderPlus.tsx
1146
+ var React17 = __toESM(require("react"));
1147
+ var FolderPlus = ({ size = 18, ...props }) => /* @__PURE__ */ React17.createElement(
1148
+ "svg",
1149
+ {
1150
+ viewBox: "0 0 18 18",
1151
+ fill: "none",
1152
+ xmlns: "http://www.w3.org/2000/svg",
1153
+ ...props,
1154
+ width: size,
1155
+ height: size
1156
+ },
1157
+ /* @__PURE__ */ React17.createElement(
1158
+ "path",
1159
+ {
1160
+ d: "M16.5 14.25C16.5 14.6478 16.342 15.0294 16.0607 15.3107C15.7794 15.592 15.3978 15.75 15 15.75H3C2.60218 15.75 2.22064 15.592 1.93934 15.3107C1.65804 15.0294 1.5 14.6478 1.5 14.25V3.75C1.5 3.35218 1.65804 2.97064 1.93934 2.68934C2.22064 2.40804 2.60218 2.25 3 2.25H6.75L8.25 4.5H15C15.3978 4.5 15.7794 4.65804 16.0607 4.93934C16.342 5.22064 16.5 5.60218 16.5 6V14.25Z",
1161
+ stroke: "currentColor",
1162
+ strokeLinecap: "round",
1163
+ strokeLinejoin: "round"
1164
+ }
1165
+ ),
1166
+ /* @__PURE__ */ React17.createElement(
1167
+ "path",
1168
+ {
1169
+ d: "M9 8.25V12.75",
1170
+ stroke: "currentColor",
1171
+ strokeLinecap: "round",
1172
+ strokeLinejoin: "round"
1173
+ }
1174
+ ),
1175
+ /* @__PURE__ */ React17.createElement(
1176
+ "path",
1177
+ {
1178
+ d: "M6.75 10.5H11.25",
1179
+ stroke: "currentColor",
1180
+ strokeLinecap: "round",
1181
+ strokeLinejoin: "round"
1182
+ }
1183
+ )
1184
+ );
1185
+ var FolderPlus_default = FolderPlus;
1186
+
1187
+ // src/icons/Link.tsx
1188
+ var React18 = __toESM(require("react"));
1189
+ var Link = ({ size = 18, ...props }) => /* @__PURE__ */ React18.createElement(
1190
+ "svg",
1191
+ {
1192
+ xmlns: "http://www.w3.org/2000/svg",
1193
+ viewBox: "0 0 18 18",
1194
+ fill: "none",
1195
+ ...props,
1196
+ width: size,
1197
+ height: size
1198
+ },
1199
+ /* @__PURE__ */ React18.createElement(
1200
+ "path",
1201
+ {
1202
+ d: "M7.5 9.75C7.82209 10.1806 8.23302 10.5369 8.70491 10.7947C9.17681 11.0525 9.69863 11.2058 10.235 11.2442C10.7713 11.2827 11.3097 11.2053 11.8135 11.0173C12.3173 10.8294 12.7748 10.5353 13.155 10.155L15.405 7.905C16.0881 7.19774 16.4661 6.25048 16.4575 5.26724C16.449 4.284 16.0546 3.34346 15.3593 2.64818C14.664 1.9529 13.7235 1.55851 12.7403 1.54997C11.757 1.54143 10.8098 1.9194 10.1025 2.6025L8.8125 3.885",
1203
+ stroke: "currentColor",
1204
+ strokeLinecap: "round",
1205
+ strokeLinejoin: "round"
1206
+ }
1207
+ ),
1208
+ /* @__PURE__ */ React18.createElement(
1209
+ "path",
1210
+ {
1211
+ d: "M10.5 8.25C10.1779 7.8194 9.76698 7.46311 9.29508 7.2053C8.82319 6.94748 8.30137 6.79416 7.76501 6.75575C7.22865 6.71734 6.69031 6.79473 6.18649 6.98266C5.68267 7.1706 5.22516 7.4647 4.845 7.845L2.595 10.095C1.9119 10.8023 1.53393 11.7495 1.54247 12.7328C1.55101 13.716 1.9454 14.6565 2.64068 15.3518C3.33596 16.0471 4.2765 16.4415 5.25974 16.45C6.24298 16.4586 7.19024 16.0806 7.8975 15.3975L9.18 14.115",
1212
+ stroke: "currentColor",
1213
+ strokeLinecap: "round",
1214
+ strokeLinejoin: "round"
1215
+ }
1216
+ )
1217
+ );
1218
+ var Link_default = Link;
1219
+
1220
+ // src/icons/RefreshCcw.tsx
1221
+ var React19 = __toESM(require("react"));
1222
+ var RefreshCcw = ({ size = 18, ...props }) => /* @__PURE__ */ React19.createElement(
1223
+ "svg",
1224
+ {
1225
+ viewBox: "0 0 18 18",
1226
+ fill: "none",
1227
+ xmlns: "http://www.w3.org/2000/svg",
1228
+ ...props,
1229
+ width: size,
1230
+ height: size
1231
+ },
1232
+ /* @__PURE__ */ React19.createElement(
1233
+ "path",
1234
+ {
1235
+ d: "M0.75 3V7.5H5.25",
1236
+ stroke: "currentColor",
1237
+ strokeLinecap: "round",
1238
+ strokeLinejoin: "round"
1239
+ }
1240
+ ),
1241
+ /* @__PURE__ */ React19.createElement(
1242
+ "path",
1243
+ {
1244
+ d: "M17.25 15V10.5H12.75",
1245
+ stroke: "currentColor",
1246
+ strokeLinecap: "round",
1247
+ strokeLinejoin: "round"
1248
+ }
1249
+ ),
1250
+ /* @__PURE__ */ React19.createElement(
1251
+ "path",
1252
+ {
1253
+ d: "M15.3675 6.75C14.9871 5.67508 14.3407 4.71405 13.4884 3.95656C12.6361 3.19907 11.6059 2.66982 10.4938 2.41819C9.38167 2.16656 8.22393 2.20075 7.12861 2.51758C6.03328 2.8344 5.03606 3.42353 4.23 4.23L0.75 7.5M17.25 10.5L13.77 13.77C12.9639 14.5765 11.9667 15.1656 10.8714 15.4824C9.77607 15.7992 8.61833 15.8334 7.50621 15.5818C6.3941 15.3302 5.36385 14.8009 4.5116 14.0434C3.65935 13.2859 3.01288 12.3249 2.6325 11.25",
1254
+ stroke: "currentColor",
1255
+ strokeLinecap: "round",
1256
+ strokeLinejoin: "round"
1257
+ }
1258
+ )
1259
+ );
1260
+ var RefreshCcw_default = RefreshCcw;
1261
+
1262
+ // src/icons/ScissorsFullOpen.tsx
1263
+ var React20 = __toESM(require("react"));
1264
+ var ScissorsFullOpen = ({ size = 12, ...props }) => /* @__PURE__ */ React20.createElement(
1265
+ "svg",
1266
+ {
1267
+ viewBox: "0 0 12 12",
1268
+ fill: "none",
1269
+ xmlns: "http://www.w3.org/2000/svg",
1270
+ ...props,
1271
+ width: size,
1272
+ height: size
1273
+ },
1274
+ /* @__PURE__ */ React20.createElement("g", { id: "scissors" }, /* @__PURE__ */ React20.createElement(
1275
+ "path",
1276
+ {
1277
+ id: "Vector",
1278
+ d: "M3 4.5C3.82843 4.5 4.5 3.82843 4.5 3C4.5 2.17157 3.82843 1.5 3 1.5C2.17157 1.5 1.5 2.17157 1.5 3C1.5 3.82843 2.17157 4.5 3 4.5Z",
1279
+ stroke: "currentColor",
1280
+ strokeLinecap: "round",
1281
+ strokeLinejoin: "round"
1282
+ }
1283
+ ), /* @__PURE__ */ React20.createElement(
1284
+ "path",
1285
+ {
1286
+ id: "Vector_2",
1287
+ d: "M3 10.5C3.82843 10.5 4.5 9.82843 4.5 9C4.5 8.17157 3.82843 7.5 3 7.5C2.17157 7.5 1.5 8.17157 1.5 9C1.5 9.82843 2.17157 10.5 3 10.5Z",
1288
+ stroke: "currentColor",
1289
+ strokeLinecap: "round",
1290
+ strokeLinejoin: "round"
1291
+ }
1292
+ ), /* @__PURE__ */ React20.createElement(
1293
+ "path",
1294
+ {
1295
+ id: "Vector_3",
1296
+ d: "M10 2L4.06 7.94",
1297
+ stroke: "currentColor",
1298
+ strokeLinecap: "round",
1299
+ strokeLinejoin: "round"
1300
+ }
1301
+ ), /* @__PURE__ */ React20.createElement(
1302
+ "path",
1303
+ {
1304
+ id: "Vector_4",
1305
+ d: "M7.235 7.23999L10 9.99999",
1306
+ stroke: "currentColor",
1307
+ strokeLinecap: "round",
1308
+ strokeLinejoin: "round"
1309
+ }
1310
+ ), /* @__PURE__ */ React20.createElement(
1311
+ "path",
1312
+ {
1313
+ id: "Vector_5",
1314
+ d: "M4.06 4.06006L6 6.00006",
1315
+ stroke: "currentColor",
1316
+ strokeLinecap: "round",
1317
+ strokeLinejoin: "round"
1318
+ }
1319
+ ))
1320
+ );
1321
+ var ScissorsFullOpen_default = ScissorsFullOpen;
1322
+
1323
+ // src/components/Input/Input.tsx
1324
+ var import_react15 = __toESM(require("react"));
1325
+ var import_classnames3 = __toESM(require("classnames"));
1326
+ var Input = ({ className, ...props }) => {
1327
+ const baseClassName = (0, import_classnames3.default)("Layer__input", className);
1328
+ return /* @__PURE__ */ import_react15.default.createElement("input", { ...props, className: baseClassName });
1329
+ };
1330
+
1331
+ // src/components/Input/InputGroup.tsx
1332
+ var import_react18 = __toESM(require("react"));
1333
+
1334
+ // src/components/Typography/Text.tsx
1335
+ var import_react16 = __toESM(require("react"));
1336
+ var import_classnames4 = __toESM(require("classnames"));
1337
+ var Text = ({
1338
+ as: Component = "p",
1339
+ className,
1340
+ children,
1341
+ size = "md" /* md */,
1342
+ weight = "normal" /* normal */,
1343
+ withTooltip,
1344
+ ...props
1345
+ }) => {
1346
+ const baseClassName = (0, import_classnames4.default)(
1347
+ `Layer__text Layer__text--${size} Layer__text--${weight}`,
1348
+ className
1349
+ );
1350
+ if (withTooltip) {
1351
+ return /* @__PURE__ */ import_react16.default.createElement(
1352
+ TextWithTooltip,
758
1353
  {
759
- amount: bankTransaction.amount,
760
- inputValue: centsToDollars(bankTransaction.amount),
761
- category: defaultCategory
762
- }
763
- ],
764
- description: "",
765
- file: void 0
766
- });
767
- const addSplit = () => updateRowState({
768
- ...rowState,
769
- splits: [
770
- ...rowState.splits,
771
- { amount: 0, inputValue: "0.00", category: defaultCategory }
772
- ]
773
- });
774
- const removeSplit = () => updateRowState({
775
- ...rowState,
776
- splits: rowState.splits.slice(0, -1)
777
- });
778
- const updateAmounts = (rowNumber) => (event) => {
779
- const newAmount = dollarsToCents(event.target.value) || 0;
780
- const newDisplaying = event.target.value;
781
- const splitTotal = rowState.splits.slice(0, -1).reduce((sum, split, index) => {
782
- const amount = index === rowNumber ? newAmount : split.amount;
783
- return sum + amount;
784
- }, 0);
785
- const remaining = bankTransaction.amount - splitTotal;
786
- rowState.splits[rowNumber].amount = newAmount;
787
- rowState.splits[rowNumber].inputValue = newDisplaying;
788
- rowState.splits[rowState.splits.length - 1].amount = remaining;
789
- rowState.splits[rowState.splits.length - 1].inputValue = centsToDollars(remaining);
790
- updateRowState({ ...rowState });
791
- };
792
- const onBlur = (event) => {
793
- if (event.target.value === "") {
794
- const [_, index] = event.target.name.split("-");
795
- rowState.splits[parseInt(index)].inputValue = "0.00";
796
- updateRowState({ ...rowState });
1354
+ as: Component,
1355
+ className: baseClassName,
1356
+ size,
1357
+ weight,
1358
+ withTooltip,
1359
+ ...props
1360
+ },
1361
+ children
1362
+ );
1363
+ }
1364
+ return /* @__PURE__ */ import_react16.default.createElement(Component, { ...props, className: baseClassName }, children);
1365
+ };
1366
+ var TextWithTooltip = ({
1367
+ as: Component = "p",
1368
+ className,
1369
+ children,
1370
+ size = "md" /* md */,
1371
+ weight = "normal" /* normal */,
1372
+ withTooltip = "whenTruncated" /* whenTruncated */,
1373
+ tooltipOptions,
1374
+ ...props
1375
+ }) => {
1376
+ const textElementRef = (0, import_react16.useRef)();
1377
+ const compareSize = () => {
1378
+ if (textElementRef.current) {
1379
+ const compare = textElementRef.current.children[0].scrollWidth > textElementRef.current.children[0].clientWidth;
1380
+ setHover(compare);
797
1381
  }
798
1382
  };
799
- const onChangePurpose = (event) => setPurpose(
800
- event.target.value === "match" /* match */ ? "match" /* match */ : "categorize" /* categorize */
1383
+ (0, import_react16.useEffect)(() => {
1384
+ compareSize();
1385
+ window.addEventListener("resize", compareSize);
1386
+ }, []);
1387
+ (0, import_react16.useEffect)(
1388
+ () => () => {
1389
+ window.removeEventListener("resize", compareSize);
1390
+ },
1391
+ []
1392
+ );
1393
+ const [hoverStatus, setHover] = (0, import_react16.useState)(false);
1394
+ const contentClassName = (0, import_classnames4.default)(
1395
+ "Layer__tooltip",
1396
+ tooltipOptions?.contentClassName
801
1397
  );
802
- const changeCategory = (index, newValue) => {
803
- rowState.splits[index].category = newValue;
804
- updateRowState({ ...rowState });
1398
+ return /* @__PURE__ */ import_react16.default.createElement(
1399
+ Tooltip,
1400
+ {
1401
+ disabled: !hoverStatus,
1402
+ offset: tooltipOptions?.offset,
1403
+ shift: tooltipOptions?.shift
1404
+ },
1405
+ /* @__PURE__ */ import_react16.default.createElement(TooltipTrigger, null, /* @__PURE__ */ import_react16.default.createElement(Component, { className, ref: textElementRef, ...props }, children)),
1406
+ /* @__PURE__ */ import_react16.default.createElement(TooltipContent, { className: contentClassName }, children)
1407
+ );
1408
+ };
1409
+
1410
+ // src/components/Typography/Heading.tsx
1411
+ var import_react17 = __toESM(require("react"));
1412
+ var import_classnames5 = __toESM(require("classnames"));
1413
+ var Heading = ({
1414
+ as: Component = "h2",
1415
+ className,
1416
+ children,
1417
+ size = "primary" /* primary */
1418
+ }) => {
1419
+ const baseClassName = (0, import_classnames5.default)(
1420
+ `Layer__heading Layer__heading--${size}`,
1421
+ className
1422
+ );
1423
+ return /* @__PURE__ */ import_react17.default.createElement(Component, { className: baseClassName }, children);
1424
+ };
1425
+
1426
+ // src/components/Input/InputGroup.tsx
1427
+ var import_classnames6 = __toESM(require("classnames"));
1428
+ var InputGroup = ({
1429
+ label,
1430
+ name,
1431
+ className,
1432
+ children
1433
+ }) => {
1434
+ const baseClassName = (0, import_classnames6.default)("Layer__input-group", className);
1435
+ return /* @__PURE__ */ import_react18.default.createElement("div", { className: baseClassName }, label && /* @__PURE__ */ import_react18.default.createElement(
1436
+ Text,
1437
+ {
1438
+ as: "label",
1439
+ size: "sm" /* sm */,
1440
+ className: "Layer__input-label",
1441
+ htmlFor: name
1442
+ },
1443
+ label
1444
+ ), children);
1445
+ };
1446
+
1447
+ // src/components/Input/FileInput.tsx
1448
+ var import_react19 = __toESM(require("react"));
1449
+
1450
+ // src/icons/UploadCloud.tsx
1451
+ var React25 = __toESM(require("react"));
1452
+ var UploadCloud = ({ size = 18, ...props }) => /* @__PURE__ */ React25.createElement(
1453
+ "svg",
1454
+ {
1455
+ viewBox: "0 0 18 18",
1456
+ fill: "none",
1457
+ xmlns: "http://www.w3.org/2000/svg",
1458
+ ...props,
1459
+ width: size,
1460
+ height: size
1461
+ },
1462
+ /* @__PURE__ */ React25.createElement(
1463
+ "path",
1464
+ {
1465
+ d: "M12 12L9 9L6 12",
1466
+ stroke: "currentColor",
1467
+ strokeLinecap: "round",
1468
+ strokeLinejoin: "round"
1469
+ }
1470
+ ),
1471
+ /* @__PURE__ */ React25.createElement(
1472
+ "path",
1473
+ {
1474
+ d: "M9 9V15.75",
1475
+ stroke: "currentColor",
1476
+ strokeLinecap: "round",
1477
+ strokeLinejoin: "round"
1478
+ }
1479
+ ),
1480
+ /* @__PURE__ */ React25.createElement(
1481
+ "path",
1482
+ {
1483
+ d: "M15.2925 13.7925C16.024 13.3937 16.6019 12.7626 16.9349 11.999C17.2679 11.2353 17.3372 10.3824 17.1317 9.57501C16.9262 8.7676 16.4576 8.05162 15.8 7.54007C15.1424 7.02852 14.3332 6.75054 13.5 6.74999H12.555C12.328 5.87192 11.9049 5.05674 11.3175 4.36573C10.7301 3.67473 9.99364 3.12588 9.16358 2.76044C8.33352 2.39501 7.43141 2.22251 6.52509 2.2559C5.61876 2.28929 4.7318 2.52771 3.93088 2.95324C3.12997 3.37876 2.43593 3.98032 1.90097 4.71267C1.366 5.44503 1.00402 6.28914 0.842236 7.18153C0.680453 8.07393 0.72308 8.99139 0.966911 9.86493C1.21074 10.7385 1.64943 11.5454 2.25 12.225",
1484
+ stroke: "currentColor",
1485
+ strokeLinecap: "round",
1486
+ strokeLinejoin: "round"
1487
+ }
1488
+ ),
1489
+ /* @__PURE__ */ React25.createElement(
1490
+ "path",
1491
+ {
1492
+ d: "M12 12L9 9L6 12",
1493
+ stroke: "currentColor",
1494
+ strokeLinecap: "round",
1495
+ strokeLinejoin: "round"
1496
+ }
1497
+ )
1498
+ );
1499
+ var UploadCloud_default = UploadCloud;
1500
+
1501
+ // src/components/Input/FileInput.tsx
1502
+ var FileInput = ({ text = "Upload", onUpload }) => {
1503
+ const hiddenFileInput = (0, import_react19.useRef)(null);
1504
+ const onClick = () => {
1505
+ if (hiddenFileInput.current) {
1506
+ hiddenFileInput.current.click();
1507
+ }
805
1508
  };
806
- const save = () => categorizeBankTransaction2(
807
- bankTransaction.id,
808
- rowState.splits.length === 1 ? {
809
- type: "Category",
810
- category: {
811
- type: "StableName",
812
- stable_name: rowState?.splits[0].category?.stable_name || rowState?.splits[0].category?.category
813
- }
814
- } : {
815
- type: "Split",
816
- entries: rowState.splits.map((split) => ({
817
- category: split.category?.stable_name || split.category?.category,
818
- amount: split.amount
819
- }))
820
- }
821
- ).then(close);
822
- const className = "Layer__expanded-bank-transaction-row";
823
- return /* @__PURE__ */ import_react9.default.createElement("div", { className }, /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__purpose-button` }, /* @__PURE__ */ import_react9.default.createElement(
824
- RadioButtonGroup,
825
- {
826
- name: `purpose-${bankTransaction.id}`,
827
- size: "small",
828
- buttons: [
829
- { value: "categorize", label: "Categorize" },
830
- { value: "match", label: "Match", disabled: true }
831
- ],
832
- selected: purpose,
833
- onChange: onChangePurpose
1509
+ const onChange = (event) => {
1510
+ if (event.target.files && event.target.files.length > 0 && onUpload) {
1511
+ const fileUploaded = event.target.files[0];
1512
+ onUpload(fileUploaded);
834
1513
  }
835
- )), /* @__PURE__ */ import_react9.default.createElement(
836
- "div",
1514
+ };
1515
+ return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement(
1516
+ Button,
837
1517
  {
838
- className: `${className}__content`,
839
- id: `expanded-${bankTransaction.id}`
1518
+ onClick,
1519
+ variant: "secondary" /* secondary */,
1520
+ leftIcon: /* @__PURE__ */ import_react19.default.createElement(UploadCloud_default, null)
840
1521
  },
841
- /* @__PURE__ */ import_react9.default.createElement(
842
- "div",
843
- {
844
- className: `${className}__table-cell ${className}__table-cell--header`
1522
+ text
1523
+ ), /* @__PURE__ */ import_react19.default.createElement(
1524
+ "input",
1525
+ {
1526
+ type: "file",
1527
+ onChange,
1528
+ ref: hiddenFileInput,
1529
+ style: { display: "none" }
1530
+ }
1531
+ ));
1532
+ };
1533
+
1534
+ // src/components/Textarea/Textarea.tsx
1535
+ var import_react20 = __toESM(require("react"));
1536
+ var import_classnames7 = __toESM(require("classnames"));
1537
+ var Textarea = ({
1538
+ className,
1539
+ ...props
1540
+ }) => {
1541
+ const baseClassName = (0, import_classnames7.default)("Layer__textarea", className);
1542
+ return /* @__PURE__ */ import_react20.default.createElement("textarea", { ...props, className: baseClassName });
1543
+ };
1544
+
1545
+ // src/components/Toggle/Toggle.tsx
1546
+ var import_react21 = __toESM(require("react"));
1547
+ var import_classnames8 = __toESM(require("classnames"));
1548
+ var Toggle = ({
1549
+ name,
1550
+ options,
1551
+ selected,
1552
+ onChange,
1553
+ size = "medium" /* medium */
1554
+ }) => {
1555
+ const [currentWidth, setCurrentWidth] = (0, import_react21.useState)(0);
1556
+ const [thumbPos, setThumbPos] = (0, import_react21.useState)({ left: 0, width: 0 });
1557
+ const [initialized, setInitialized] = (0, import_react21.useState)(false);
1558
+ const toggleRef = useElementSize((a, b, c) => {
1559
+ if (c.width && c?.width !== currentWidth) {
1560
+ setCurrentWidth(c.width);
1561
+ }
1562
+ });
1563
+ const selectedValue = selected || options[0].value;
1564
+ const baseClassName = (0, import_classnames8.default)(
1565
+ "Layer__toggle",
1566
+ `Layer__toggle--${size}`,
1567
+ initialized ? "Layer__toggle--initialized" : ""
1568
+ );
1569
+ const handleChange = (e) => {
1570
+ updateThumbPosition(Number(e.target.getAttribute("data-idx") ?? 0));
1571
+ onChange(e);
1572
+ };
1573
+ const updateThumbPosition = (active) => {
1574
+ if (!toggleRef?.current) {
1575
+ return;
1576
+ }
1577
+ const optionsNodes = [...toggleRef.current.children].filter(
1578
+ (c) => c.className.includes("Layer__toggle-option")
1579
+ );
1580
+ let shift2 = 0;
1581
+ let width = thumbPos.width;
1582
+ optionsNodes.forEach((c, i) => {
1583
+ if (i < active) {
1584
+ shift2 = shift2 + c.offsetWidth;
1585
+ } else if (i === active) {
1586
+ width = c.offsetWidth;
845
1587
  }
846
- ),
847
- /* @__PURE__ */ import_react9.default.createElement(
848
- "div",
849
- {
850
- className: `${className}__table-cell ${className}__table-cell--header`
851
- },
852
- "Category"
853
- ),
854
- /* @__PURE__ */ import_react9.default.createElement(
855
- "div",
856
- {
857
- className: `${className}__table-cell ${className}__table-cell--header`
858
- },
859
- "Description"
860
- ),
861
- /* @__PURE__ */ import_react9.default.createElement(
862
- "div",
863
- {
864
- className: `${className}__table-cell ${className}__table-cell--header`
865
- },
866
- "Receipt"
867
- ),
868
- /* @__PURE__ */ import_react9.default.createElement(
869
- "div",
870
- {
871
- className: `${className}__table-cell ${className}__table-cell--header`
1588
+ });
1589
+ shift2 = shift2 + (size === "medium" /* medium */ ? 2 : 1);
1590
+ setThumbPos({ left: shift2, width });
1591
+ };
1592
+ (0, import_react21.useEffect)(() => {
1593
+ const selectedIndex = getSelectedIndex();
1594
+ updateThumbPosition(selectedIndex);
1595
+ setTimeout(() => {
1596
+ setInitialized(true);
1597
+ }, 400);
1598
+ }, []);
1599
+ (0, import_react21.useEffect)(() => {
1600
+ const selectedIndex = getSelectedIndex();
1601
+ updateThumbPosition(selectedIndex);
1602
+ }, [currentWidth]);
1603
+ const getSelectedIndex = () => {
1604
+ let selectedIndex = options.findIndex(
1605
+ (option) => option.value === selectedValue
1606
+ );
1607
+ if (selectedIndex === -1) {
1608
+ return 0;
1609
+ }
1610
+ return selectedIndex;
1611
+ };
1612
+ return /* @__PURE__ */ import_react21.default.createElement("div", { className: baseClassName, ref: toggleRef }, options.map((option, index) => /* @__PURE__ */ import_react21.default.createElement(
1613
+ ToggleOption,
1614
+ {
1615
+ ...option,
1616
+ size,
1617
+ key: option.value,
1618
+ name,
1619
+ checked: selectedValue === option.value,
1620
+ onChange: handleChange,
1621
+ disabled: option.disabled ?? false,
1622
+ index
1623
+ }
1624
+ )), /* @__PURE__ */ import_react21.default.createElement("span", { className: "Layer__toggle__thumb", style: { ...thumbPos } }));
1625
+ };
1626
+ var ToggleOption = ({
1627
+ checked,
1628
+ label,
1629
+ name,
1630
+ onChange,
1631
+ value,
1632
+ size,
1633
+ leftIcon,
1634
+ disabled,
1635
+ index
1636
+ }) => {
1637
+ return /* @__PURE__ */ import_react21.default.createElement("label", { className: `Layer__toggle-option`, "data-checked": checked }, /* @__PURE__ */ import_react21.default.createElement(
1638
+ "input",
1639
+ {
1640
+ type: "radio",
1641
+ checked,
1642
+ name,
1643
+ onChange,
1644
+ value,
1645
+ disabled: disabled ?? false,
1646
+ "data-idx": index
1647
+ }
1648
+ ), /* @__PURE__ */ import_react21.default.createElement("span", { className: "Layer__toggle-option-content" }, leftIcon && /* @__PURE__ */ import_react21.default.createElement("span", { className: "Layer__toggle-option__icon" }, leftIcon), /* @__PURE__ */ import_react21.default.createElement("span", null, label)));
1649
+ };
1650
+
1651
+ // src/components/ExpandedBankTransactionRow/ExpandedBankTransactionRow.tsx
1652
+ var ExpandedBankTransactionRow = (0, import_react22.forwardRef)(
1653
+ ({
1654
+ bankTransaction,
1655
+ isOpen = false,
1656
+ asListItem = false,
1657
+ showSubmitButton = false
1658
+ }, ref) => {
1659
+ const { categorize: categorizeBankTransaction2 } = useBankTransactions();
1660
+ const [purpose, setPurpose] = (0, import_react22.useState)("categorize" /* categorize */);
1661
+ const defaultCategory = bankTransaction.category || bankTransaction.categorization_flow?.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ && bankTransaction.categorization_flow?.suggestions?.[0];
1662
+ const [rowState, updateRowState] = (0, import_react22.useState)({
1663
+ splits: [
1664
+ {
1665
+ amount: bankTransaction.amount,
1666
+ inputValue: centsToDollars(bankTransaction.amount),
1667
+ category: defaultCategory
1668
+ }
1669
+ ],
1670
+ description: "",
1671
+ file: void 0
1672
+ });
1673
+ const addSplit = () => updateRowState({
1674
+ ...rowState,
1675
+ splits: [
1676
+ ...rowState.splits,
1677
+ { amount: 0, inputValue: "0.00", category: defaultCategory }
1678
+ ]
1679
+ });
1680
+ const removeSplit = () => updateRowState({
1681
+ ...rowState,
1682
+ splits: rowState.splits.slice(0, -1)
1683
+ });
1684
+ const updateAmounts = (rowNumber) => (event) => {
1685
+ const newAmount = dollarsToCents(event.target.value) || 0;
1686
+ const newDisplaying = event.target.value;
1687
+ const splitTotal = rowState.splits.slice(0, -1).reduce((sum, split, index) => {
1688
+ const amount = index === rowNumber ? newAmount : split.amount;
1689
+ return sum + amount;
1690
+ }, 0);
1691
+ const remaining = bankTransaction.amount - splitTotal;
1692
+ rowState.splits[rowNumber].amount = newAmount;
1693
+ rowState.splits[rowNumber].inputValue = newDisplaying;
1694
+ rowState.splits[rowState.splits.length - 1].amount = remaining;
1695
+ rowState.splits[rowState.splits.length - 1].inputValue = centsToDollars(remaining);
1696
+ updateRowState({ ...rowState });
1697
+ };
1698
+ const onBlur = (event) => {
1699
+ if (event.target.value === "") {
1700
+ const [_, index] = event.target.name.split("-");
1701
+ rowState.splits[parseInt(index)].inputValue = "0.00";
1702
+ updateRowState({ ...rowState });
872
1703
  }
873
- ),
874
- /* @__PURE__ */ import_react9.default.createElement(
875
- "div",
876
- {
877
- className: `${className}__table-cell ${className}__table-cell--header`
1704
+ };
1705
+ const onChangePurpose = (event) => setPurpose(
1706
+ event.target.value === "match" /* match */ ? "match" /* match */ : "categorize" /* categorize */
1707
+ );
1708
+ const changeCategory = (index, newValue) => {
1709
+ rowState.splits[index].category = newValue;
1710
+ updateRowState({ ...rowState });
1711
+ };
1712
+ const save = () => categorizeBankTransaction2(
1713
+ bankTransaction.id,
1714
+ rowState.splits.length === 1 ? {
1715
+ type: "Category",
1716
+ category: {
1717
+ type: "StableName",
1718
+ stable_name: rowState?.splits[0].category?.stable_name || rowState?.splits[0].category?.category
1719
+ }
1720
+ } : {
1721
+ type: "Split",
1722
+ entries: rowState.splits.map((split) => ({
1723
+ category: split.category?.stable_name || split.category?.category,
1724
+ amount: split.amount
1725
+ }))
878
1726
  }
879
- ),
880
- /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }, rowState.splits.length === 1 ? /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__button--split`, onClick: addSplit }, /* @__PURE__ */ import_react9.default.createElement(LinkBroken_default, { className: `${className}__svg`, size: 18 }), "Split") : /* @__PURE__ */ import_react9.default.createElement(
881
- "div",
1727
+ ).catch((e) => console.error(e));
1728
+ (0, import_react22.useImperativeHandle)(ref, () => ({
1729
+ save
1730
+ }));
1731
+ const className = "Layer__expanded-bank-transaction-row";
1732
+ return /* @__PURE__ */ import_react22.default.createElement(
1733
+ "span",
882
1734
  {
883
- className: `${className}__button--merge`,
884
- onClick: removeSplit
1735
+ className: `${className} ${className}--${isOpen ? "expanded" : "collapsed"}`
885
1736
  },
886
- /* @__PURE__ */ import_react9.default.createElement(Link_default, { className: `${className}__svg`, size: 18 }),
887
- "Merge"
888
- )),
889
- /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }, rowState.splits.map((split, index) => /* @__PURE__ */ import_react9.default.createElement(
890
- "div",
891
- {
892
- className: `${className}__table-cell--split-entry`,
893
- key: `split-${index}`
894
- },
895
- /* @__PURE__ */ import_react9.default.createElement(
896
- CategoryMenu,
1737
+ /* @__PURE__ */ import_react22.default.createElement("span", { className: `${className}__wrapper` }, /* @__PURE__ */ import_react22.default.createElement("div", { className: `${className}__content-toggle` }, /* @__PURE__ */ import_react22.default.createElement(
1738
+ Toggle,
897
1739
  {
898
- bankTransaction,
899
- name: `category-${index}`,
900
- value: split.category,
901
- onChange: (value) => changeCategory(index, value)
1740
+ name: `purpose-${bankTransaction.id}${asListItem ? "-li" : ""}`,
1741
+ size: "small" /* small */,
1742
+ options: [
1743
+ {
1744
+ value: "categorize",
1745
+ label: "Categorize",
1746
+ leftIcon: /* @__PURE__ */ import_react22.default.createElement(FolderPlus_default, { size: 15 })
1747
+ },
1748
+ {
1749
+ value: "match",
1750
+ label: "Match",
1751
+ disabled: true,
1752
+ leftIcon: /* @__PURE__ */ import_react22.default.createElement(RefreshCcw_default, { size: 15 })
1753
+ }
1754
+ ],
1755
+ selected: purpose,
1756
+ onChange: onChangePurpose
902
1757
  }
903
- ),
904
- rowState.splits.length > 1 && /* @__PURE__ */ import_react9.default.createElement(
905
- "input",
1758
+ )), /* @__PURE__ */ import_react22.default.createElement(
1759
+ "div",
906
1760
  {
907
- type: "text",
908
- name: `split-${index}`,
909
- disabled: index + 1 === rowState.splits.length,
910
- onChange: updateAmounts(index),
911
- value: split.inputValue,
912
- onBlur,
913
- className: `${className}__split-amount${split.amount < 0 ? "--negative" : ""}`
1761
+ className: `${className}__content`,
1762
+ id: `expanded-${bankTransaction.id}`
1763
+ },
1764
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: `${className}__splits` }, /* @__PURE__ */ import_react22.default.createElement("div", { className: `${className}__splits-inputs` }, rowState.splits.map((split, index) => /* @__PURE__ */ import_react22.default.createElement(
1765
+ "div",
1766
+ {
1767
+ className: `${className}__table-cell--split-entry`,
1768
+ key: `split-${index}`
1769
+ },
1770
+ rowState.splits.length > 1 && /* @__PURE__ */ import_react22.default.createElement(
1771
+ Input,
1772
+ {
1773
+ type: "text",
1774
+ name: `split-${index}${asListItem ? "-li" : ""}`,
1775
+ disabled: index + 1 === rowState.splits.length,
1776
+ onChange: updateAmounts(index),
1777
+ value: split.inputValue,
1778
+ onBlur,
1779
+ className: `${className}__split-amount${split.amount < 0 ? "--negative" : ""}`
1780
+ }
1781
+ ),
1782
+ /* @__PURE__ */ import_react22.default.createElement(
1783
+ CategoryMenu,
1784
+ {
1785
+ bankTransaction,
1786
+ name: `category-${index}${asListItem ? "-li" : ""}`,
1787
+ value: split.category,
1788
+ onChange: (value) => changeCategory(index, value),
1789
+ className: "Layer__category-menu--full"
1790
+ }
1791
+ )
1792
+ ))), /* @__PURE__ */ import_react22.default.createElement("div", { className: `${className}__splits-buttons` }, rowState.splits.length === 1 ? /* @__PURE__ */ import_react22.default.createElement(
1793
+ Button,
1794
+ {
1795
+ onClick: addSplit,
1796
+ leftIcon: /* @__PURE__ */ import_react22.default.createElement(ScissorsFullOpen_default, { size: 14 }),
1797
+ variant: "secondary" /* secondary */
1798
+ },
1799
+ "Split"
1800
+ ) : /* @__PURE__ */ import_react22.default.createElement(
1801
+ Button,
1802
+ {
1803
+ onClick: removeSplit,
1804
+ leftIcon: /* @__PURE__ */ import_react22.default.createElement(Link_default, { size: 14 }),
1805
+ variant: "secondary" /* secondary */
1806
+ },
1807
+ "Merge"
1808
+ ))),
1809
+ /* @__PURE__ */ import_react22.default.createElement(
1810
+ InputGroup,
1811
+ {
1812
+ className: `${className}__description`,
1813
+ name: "description",
1814
+ label: "Description"
1815
+ },
1816
+ /* @__PURE__ */ import_react22.default.createElement(Textarea, { name: "description", placeholder: "Enter description" })
1817
+ ),
1818
+ /* @__PURE__ */ import_react22.default.createElement("div", { className: `${className}__file-upload` }, /* @__PURE__ */ import_react22.default.createElement(FileInput, { text: "Upload receipt" })),
1819
+ asListItem || showSubmitButton ? /* @__PURE__ */ import_react22.default.createElement("div", { className: `${className}__submit-btn` }, /* @__PURE__ */ import_react22.default.createElement(
1820
+ SubmitButton,
1821
+ {
1822
+ onClick: () => {
1823
+ if (!bankTransaction.processing) {
1824
+ save();
1825
+ }
1826
+ },
1827
+ className: "Layer__bank-transaction__submit-btn",
1828
+ processing: bankTransaction.processing,
1829
+ error: bankTransaction.error,
1830
+ active: true
1831
+ },
1832
+ "Approve"
1833
+ )) : null
1834
+ ))
1835
+ );
1836
+ }
1837
+ );
1838
+
1839
+ // src/components/Pill/Pill.tsx
1840
+ var import_react23 = __toESM(require("react"));
1841
+ var Pill = ({ children }) => /* @__PURE__ */ import_react23.default.createElement("span", { className: "Layer__pill" }, children);
1842
+
1843
+ // src/components/BankTransactionListItem/BankTransactionListItem.tsx
1844
+ var import_classnames9 = __toESM(require("classnames"));
1845
+ var import_date_fns4 = require("date-fns");
1846
+ var isCredit = ({ direction }) => direction === "CREDIT" /* CREDIT */;
1847
+ var BankTransactionListItem = ({
1848
+ dateFormat: dateFormat2,
1849
+ bankTransaction,
1850
+ isOpen,
1851
+ toggleOpen,
1852
+ editable
1853
+ }) => {
1854
+ const expandedRowRef = (0, import_react24.useRef)(null);
1855
+ const [removed, setRemoved] = (0, import_react24.useState)(false);
1856
+ const { categorize: categorizeBankTransaction2 } = useBankTransactions();
1857
+ const [selectedCategory, setSelectedCategory] = (0, import_react24.useState)(
1858
+ bankTransaction.categorization_flow?.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ ? bankTransaction.categorization_flow.suggestions[0] : void 0
1859
+ );
1860
+ const save = () => {
1861
+ if (isOpen && expandedRowRef?.current) {
1862
+ expandedRowRef?.current?.save();
1863
+ toggleOpen(bankTransaction.id);
1864
+ return;
1865
+ }
1866
+ categorizeBankTransaction2(bankTransaction.id, {
1867
+ type: "Category",
1868
+ category: {
1869
+ type: "StableName",
1870
+ stable_name: selectedCategory?.stable_name || selectedCategory?.category || ""
1871
+ }
1872
+ });
1873
+ };
1874
+ if (removed) {
1875
+ return null;
1876
+ }
1877
+ const className = "Layer__bank-transaction-list-item";
1878
+ const openClassName = isOpen ? `${className}--expanded` : "";
1879
+ const rowClassName = (0, import_classnames9.default)(
1880
+ className,
1881
+ bankTransaction.recently_categorized ? "Layer__bank-transaction-row--removing" : "",
1882
+ isOpen ? openClassName : ""
1883
+ );
1884
+ return /* @__PURE__ */ import_react24.default.createElement("li", { className: rowClassName }, /* @__PURE__ */ import_react24.default.createElement("span", { className: `${className}__heading` }, /* @__PURE__ */ import_react24.default.createElement("span", { className: `${className}__heading-date` }, (0, import_date_fns4.format)((0, import_date_fns4.parseISO)(bankTransaction.date), dateFormat2)), /* @__PURE__ */ import_react24.default.createElement("span", { className: `${className}__heading-separator` }), /* @__PURE__ */ import_react24.default.createElement("span", { className: `${className}__heading-account-name` }, bankTransaction.account_name ?? "")), /* @__PURE__ */ import_react24.default.createElement("span", { className: `${className}__body` }, /* @__PURE__ */ import_react24.default.createElement("span", { className: `${className}__body__name` }, bankTransaction.counterparty_name), /* @__PURE__ */ import_react24.default.createElement(
1885
+ "span",
1886
+ {
1887
+ className: `${className}__amount-${isCredit(bankTransaction) ? "credit" : "debit"}`
1888
+ },
1889
+ isCredit(bankTransaction) ? "+$" : " $",
1890
+ centsToDollars(bankTransaction.amount)
1891
+ ), /* @__PURE__ */ import_react24.default.createElement(
1892
+ "div",
1893
+ {
1894
+ onClick: () => toggleOpen(bankTransaction.id),
1895
+ className: "Layer__bank-transaction-row__expand-button"
1896
+ },
1897
+ /* @__PURE__ */ import_react24.default.createElement(
1898
+ ChevronDown_default,
1899
+ {
1900
+ className: `Layer__chevron ${isOpen ? "Layer__chevron__up" : "Layer__chevron__down"}`
1901
+ }
1902
+ )
1903
+ )), /* @__PURE__ */ import_react24.default.createElement("span", { className: `${className}__expanded-row` }, /* @__PURE__ */ import_react24.default.createElement(
1904
+ ExpandedBankTransactionRow,
1905
+ {
1906
+ ref: expandedRowRef,
1907
+ bankTransaction,
1908
+ close: () => toggleOpen(bankTransaction.id),
1909
+ isOpen,
1910
+ asListItem: true
1911
+ }
1912
+ )), /* @__PURE__ */ import_react24.default.createElement("span", { className: `${className}__base-row` }, editable ? /* @__PURE__ */ import_react24.default.createElement(
1913
+ CategoryMenu,
1914
+ {
1915
+ bankTransaction,
1916
+ name: `category-${bankTransaction.id}`,
1917
+ value: selectedCategory,
1918
+ onChange: setSelectedCategory,
1919
+ disabled: bankTransaction.processing
1920
+ }
1921
+ ) : null, !editable ? /* @__PURE__ */ import_react24.default.createElement(Pill, null, bankTransaction?.category?.display_name) : null, editable && /* @__PURE__ */ import_react24.default.createElement(
1922
+ SubmitButton,
1923
+ {
1924
+ onClick: () => {
1925
+ if (!bankTransaction.processing) {
1926
+ save();
914
1927
  }
915
- )
916
- ))),
917
- /* @__PURE__ */ import_react9.default.createElement(
918
- "div",
919
- {
920
- className: `${className}__table-cell ${className}__table-cell--description`
921
1928
  },
922
- /* @__PURE__ */ import_react9.default.createElement("textarea", null)
923
- ),
924
- /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }, /* @__PURE__ */ import_react9.default.createElement("input", { type: "file" })),
925
- /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }),
926
- /* @__PURE__ */ import_react9.default.createElement("div", { className: `${className}__table-cell` }, /* @__PURE__ */ import_react9.default.createElement("button", { onClick: save, className: `${className}__button--save` }, "Save"))
927
- ));
1929
+ className: "Layer__bank-transaction__submit-btn",
1930
+ processing: bankTransaction.processing,
1931
+ error: bankTransaction.error,
1932
+ iconOnly: true
1933
+ }
1934
+ )));
928
1935
  };
929
1936
 
930
- // src/components/Pill/Pill.tsx
931
- var import_react10 = __toESM(require("react"));
932
- var Pill = ({ children }) => /* @__PURE__ */ import_react10.default.createElement("span", { className: "Layer__pill" }, children);
933
-
934
1937
  // src/components/BankTransactionRow/BankTransactionRow.tsx
935
- var import_date_fns4 = require("date-fns");
936
- var isCredit = ({ direction }) => direction === "CREDIT" /* CREDIT */;
1938
+ var import_react25 = __toESM(require("react"));
1939
+ var import_classnames10 = __toESM(require("classnames"));
1940
+ var import_date_fns5 = require("date-fns");
1941
+ var isCredit2 = ({ direction }) => direction === "CREDIT" /* CREDIT */;
937
1942
  var BankTransactionRow = ({
938
1943
  dateFormat: dateFormat2,
939
1944
  bankTransaction,
@@ -941,65 +1946,269 @@ var BankTransactionRow = ({
941
1946
  toggleOpen,
942
1947
  editable
943
1948
  }) => {
1949
+ const expandedRowRef = (0, import_react25.useRef)(null);
1950
+ const [removed, setRemoved] = (0, import_react25.useState)(false);
944
1951
  const { categorize: categorizeBankTransaction2 } = useBankTransactions();
945
- const [selectedCategory, setSelectedCategory] = (0, import_react11.useState)(
946
- bankTransaction.categorization_flow.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ ? bankTransaction.categorization_flow.suggestions[0] : void 0
1952
+ const [selectedCategory, setSelectedCategory] = (0, import_react25.useState)(
1953
+ bankTransaction.categorization_flow?.type === "ASK_FROM_SUGGESTIONS" /* ASK_FROM_SUGGESTIONS */ ? bankTransaction.categorization_flow.suggestions[0] : void 0
947
1954
  );
948
- const className = "Layer__bank-transaction-row__table-cell";
949
- const openClassName = isOpen ? `${className}--expanded` : "";
950
- const save = () => categorizeBankTransaction2(bankTransaction.id, {
951
- type: "Category",
952
- category: {
953
- type: "StableName",
954
- stable_name: selectedCategory?.stable_name || selectedCategory?.category || ""
1955
+ const save = () => {
1956
+ if (isOpen && expandedRowRef?.current) {
1957
+ expandedRowRef?.current?.save();
1958
+ toggleOpen(bankTransaction.id);
1959
+ return;
955
1960
  }
956
- });
957
- return /* @__PURE__ */ import_react11.default.createElement(import_react11.default.Fragment, null, /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName} ${className}--date` }, (0, import_date_fns4.format)((0, import_date_fns4.parseISO)(bankTransaction.date), dateFormat2)), /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName}` }, bankTransaction.counterparty_name), /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName}` }, "Business Checking"), /* @__PURE__ */ import_react11.default.createElement(
958
- "div",
1961
+ categorizeBankTransaction2(bankTransaction.id, {
1962
+ type: "Category",
1963
+ category: {
1964
+ type: "StableName",
1965
+ stable_name: selectedCategory?.stable_name || selectedCategory?.category || ""
1966
+ }
1967
+ });
1968
+ };
1969
+ if (removed) {
1970
+ return null;
1971
+ }
1972
+ const className = "Layer__bank-transaction-row";
1973
+ const openClassName = isOpen ? `${className}--expanded` : "";
1974
+ const rowClassName = (0, import_classnames10.default)(
1975
+ className,
1976
+ bankTransaction.recently_categorized ? "Layer__bank-transaction-row--removing" : "",
1977
+ isOpen ? openClassName : ""
1978
+ );
1979
+ return /* @__PURE__ */ import_react25.default.createElement(import_react25.default.Fragment, null, /* @__PURE__ */ import_react25.default.createElement(
1980
+ "tr",
959
1981
  {
960
- className: `${className} ${openClassName} ${className}--amount-${isCredit(bankTransaction) ? "credit" : "debit"}`
1982
+ className: rowClassName,
1983
+ onTransitionEnd: ({ propertyName }) => {
1984
+ if (propertyName === "top") {
1985
+ setRemoved(true);
1986
+ }
1987
+ }
961
1988
  },
962
- centsToDollars(bankTransaction.amount)
963
- ), isOpen ? /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName}` }) : /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName}` }, editable ? /* @__PURE__ */ import_react11.default.createElement(
964
- CategoryMenu,
1989
+ /* @__PURE__ */ import_react25.default.createElement("td", { className: "Layer__table-cell" }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "Layer__table-cell-content" }, (0, import_date_fns5.format)((0, import_date_fns5.parseISO)(bankTransaction.date), dateFormat2))),
1990
+ /* @__PURE__ */ import_react25.default.createElement("td", { className: "Layer__table-cell Layer__bank-transactions__tx-col" }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "Layer__table-cell-content" }, /* @__PURE__ */ import_react25.default.createElement(
1991
+ Text,
1992
+ {
1993
+ as: "span",
1994
+ className: "Layer__bank-transactions__tx-text",
1995
+ withTooltip: "whenTruncated" /* whenTruncated */,
1996
+ tooltipOptions: {
1997
+ contentClassName: "Layer__bank-transactions__tx-tooltip"
1998
+ }
1999
+ },
2000
+ bankTransaction.counterparty_name
2001
+ ))),
2002
+ /* @__PURE__ */ import_react25.default.createElement("td", { className: "Layer__table-cell Layer__bank-transactions__account-col" }, /* @__PURE__ */ import_react25.default.createElement("span", { className: "Layer__table-cell-content" }, /* @__PURE__ */ import_react25.default.createElement(
2003
+ Text,
2004
+ {
2005
+ as: "span",
2006
+ className: "Layer__bank-transactions__account-text",
2007
+ withTooltip: "whenTruncated" /* whenTruncated */
2008
+ },
2009
+ bankTransaction.account_name ?? ""
2010
+ ))),
2011
+ /* @__PURE__ */ import_react25.default.createElement(
2012
+ "td",
2013
+ {
2014
+ className: `Layer__table-cell Layer__table-cell__amount-col Layer__table-cell--amount ${className}__table-cell--amount-${isCredit2(bankTransaction) ? "credit" : "debit"}`
2015
+ },
2016
+ /* @__PURE__ */ import_react25.default.createElement("span", { className: "Layer__table-cell-content" }, isCredit2(bankTransaction) ? "+$" : " $", centsToDollars(bankTransaction.amount))
2017
+ ),
2018
+ /* @__PURE__ */ import_react25.default.createElement(
2019
+ "td",
2020
+ {
2021
+ className: (0, import_classnames10.default)(
2022
+ "Layer__table-cell",
2023
+ "Layer__table-cell__category-col",
2024
+ `${className}__actions-cell`,
2025
+ `${className}__actions-cell--${isOpen ? "open" : "close"}`
2026
+ )
2027
+ },
2028
+ /* @__PURE__ */ import_react25.default.createElement(
2029
+ "span",
2030
+ {
2031
+ className: `${className}__actions-container Layer__table-cell-content`
2032
+ },
2033
+ editable && !isOpen ? /* @__PURE__ */ import_react25.default.createElement(
2034
+ CategoryMenu,
2035
+ {
2036
+ bankTransaction,
2037
+ name: `category-${bankTransaction.id}`,
2038
+ value: selectedCategory,
2039
+ onChange: setSelectedCategory,
2040
+ disabled: bankTransaction.processing
2041
+ }
2042
+ ) : null,
2043
+ !editable ? /* @__PURE__ */ import_react25.default.createElement(Text, { as: "span", className: `${className}__category-text` }, bankTransaction?.category?.display_name) : null,
2044
+ editable && /* @__PURE__ */ import_react25.default.createElement(
2045
+ SubmitButton,
2046
+ {
2047
+ onClick: () => {
2048
+ if (!bankTransaction.processing) {
2049
+ save();
2050
+ }
2051
+ },
2052
+ className: "Layer__bank-transaction__submit-btn",
2053
+ processing: bankTransaction.processing,
2054
+ error: bankTransaction.error,
2055
+ active: isOpen
2056
+ },
2057
+ "Approve"
2058
+ ),
2059
+ /* @__PURE__ */ import_react25.default.createElement(
2060
+ "div",
2061
+ {
2062
+ onClick: () => toggleOpen(bankTransaction.id),
2063
+ className: "Layer__bank-transaction-row__expand-button"
2064
+ },
2065
+ /* @__PURE__ */ import_react25.default.createElement(
2066
+ ChevronDown_default,
2067
+ {
2068
+ className: `Layer__chevron ${isOpen ? "Layer__chevron__up" : "Layer__chevron__down"}`
2069
+ }
2070
+ )
2071
+ )
2072
+ )
2073
+ )
2074
+ ), /* @__PURE__ */ import_react25.default.createElement("tr", null, /* @__PURE__ */ import_react25.default.createElement("td", { colSpan: 5 }, /* @__PURE__ */ import_react25.default.createElement(
2075
+ ExpandedBankTransactionRow,
965
2076
  {
2077
+ ref: expandedRowRef,
966
2078
  bankTransaction,
967
- name: `category-${bankTransaction.id}`,
968
- value: selectedCategory,
969
- onChange: setSelectedCategory
2079
+ close: () => toggleOpen(bankTransaction.id),
2080
+ isOpen,
2081
+ showSubmitButton: !editable
970
2082
  }
971
- ) : /* @__PURE__ */ import_react11.default.createElement(Pill, null, bankTransaction?.category?.display_name)), /* @__PURE__ */ import_react11.default.createElement("div", { className: `${className} ${openClassName} ${className}--actions` }, /* @__PURE__ */ import_react11.default.createElement(
972
- "div",
973
- {
974
- className: "Layer__bank-transaction-row__save-button",
975
- onClick: () => save()
976
- },
977
- editable && !isOpen && /* @__PURE__ */ import_react11.default.createElement(
978
- CheckedCircle_default,
979
- {
980
- size: 28,
981
- strokeColor: "#0C48E5",
982
- fillColor: "#e0e9ff"
2083
+ ))));
2084
+ };
2085
+
2086
+ // src/components/Container/Container.tsx
2087
+ var import_react26 = __toESM(require("react"));
2088
+
2089
+ // src/utils/colors.ts
2090
+ var parseStylesFromThemeConfig = (theme) => {
2091
+ let styles = {};
2092
+ if (!theme) {
2093
+ return styles;
2094
+ }
2095
+ if (theme.colors) {
2096
+ const darkColor = parseColorFromTheme("dark", theme.colors.dark);
2097
+ const lightColor = parseColorFromTheme("light", theme.colors.light);
2098
+ styles = { ...styles, ...darkColor, ...lightColor };
2099
+ }
2100
+ return styles;
2101
+ };
2102
+ var parseColorFromTheme = (colorName, color) => {
2103
+ if (!color) {
2104
+ return {};
2105
+ }
2106
+ try {
2107
+ if ("h" in color && "s" in color && "l" in color) {
2108
+ console.log("its hsl", color);
2109
+ return {
2110
+ [`--color-${colorName}-h`]: color.h,
2111
+ [`--color-${colorName}-s`]: color.s,
2112
+ [`--color-${colorName}-l`]: color.l
2113
+ };
2114
+ }
2115
+ if ("r" in color && "g" in color && "b" in color) {
2116
+ const { h, s, l } = rgbToHsl(color);
2117
+ console.log("its rgb", h, s, l);
2118
+ return {
2119
+ [`--color-${colorName}-h`]: h,
2120
+ [`--color-${colorName}-s`]: `${s}%`,
2121
+ [`--color-${colorName}-l`]: `${l}%`
2122
+ };
2123
+ }
2124
+ if ("hex" in color) {
2125
+ console.log("its hex");
2126
+ const rgb = hexToRgb(color.hex);
2127
+ if (!rgb) {
2128
+ return {};
983
2129
  }
984
- )
985
- ), /* @__PURE__ */ import_react11.default.createElement(
2130
+ const { h, s, l } = rgbToHsl({
2131
+ r: rgb.r.toString(),
2132
+ g: rgb.g.toString(),
2133
+ b: rgb.b.toString()
2134
+ });
2135
+ console.log("its hex", h, s, l);
2136
+ return {
2137
+ [`--color-${colorName}-h`]: h,
2138
+ [`--color-${colorName}-s`]: `${s}%`,
2139
+ [`--color-${colorName}-l`]: `${l}%`
2140
+ };
2141
+ }
2142
+ return {};
2143
+ } catch (_err) {
2144
+ return {};
2145
+ }
2146
+ };
2147
+ var rgbToHsl = (color) => {
2148
+ let r = Number(color.r);
2149
+ let g = Number(color.g);
2150
+ let b = Number(color.b);
2151
+ r /= 255;
2152
+ g /= 255;
2153
+ b /= 255;
2154
+ const l = Math.max(r, g, b);
2155
+ const s = l - Math.min(r, g, b);
2156
+ const h = s ? l === r ? (g - b) / s : l === g ? 2 + (b - r) / s : 4 + (r - g) / s : 0;
2157
+ return {
2158
+ h: 60 * h < 0 ? 60 * h + 360 : 60 * h,
2159
+ s: 100 * (s ? l <= 0.5 ? s / (2 * l - s) : s / (2 - (2 * l - s)) : 0),
2160
+ l: 100 * (2 * l - s) / 2
2161
+ };
2162
+ };
2163
+ var hexToRgb = (hex) => {
2164
+ const values = hex.replace(
2165
+ /^#?([a-f\d])([a-f\d])([a-f\d])$/i,
2166
+ (m, r, g, b) => "#" + r + r + g + g + b + b
2167
+ ).substring(1).match(/.{2}/g)?.map((x) => parseInt(x, 16));
2168
+ if (!values) {
2169
+ return;
2170
+ }
2171
+ return {
2172
+ r: values[0],
2173
+ g: values[1],
2174
+ b: values[2]
2175
+ };
2176
+ };
2177
+
2178
+ // src/components/Container/Container.tsx
2179
+ var Container = ({ name, className, children }) => {
2180
+ const baseClassName = `Layer__${name} ${className ?? ""}`;
2181
+ const { theme } = useLayerContext();
2182
+ const styles = parseStylesFromThemeConfig(theme);
2183
+ return /* @__PURE__ */ import_react26.default.createElement(
986
2184
  "div",
987
2185
  {
988
- onClick: () => toggleOpen(bankTransaction.id),
989
- className: "Layer__bank-transaction-row__expand-button"
2186
+ className: `Layer__component Layer__component-container ${baseClassName}`,
2187
+ style: { ...styles }
990
2188
  },
991
- isOpen ? /* @__PURE__ */ import_react11.default.createElement(ChevronUp_default, null) : /* @__PURE__ */ import_react11.default.createElement(ChevronDown_default, null)
992
- )), isOpen && /* @__PURE__ */ import_react11.default.createElement(
993
- ExpandedBankTransactionRow,
994
- {
995
- bankTransaction,
996
- close: () => toggleOpen(bankTransaction.id)
997
- }
998
- ));
2189
+ children
2190
+ );
2191
+ };
2192
+
2193
+ // src/components/Container/Header.tsx
2194
+ var import_react27 = __toESM(require("react"));
2195
+ var import_classnames11 = __toESM(require("classnames"));
2196
+ var Header = (0, import_react27.forwardRef)(
2197
+ ({ className, children, style }, ref) => {
2198
+ const baseClassName = (0, import_classnames11.default)("Layer__component-header", className);
2199
+ return /* @__PURE__ */ import_react27.default.createElement("header", { ref, className: baseClassName, style }, children);
2200
+ }
2201
+ );
2202
+
2203
+ // src/components/Loader/Loader.tsx
2204
+ var import_react28 = __toESM(require("react"));
2205
+ var Loader2 = ({ children }) => {
2206
+ return /* @__PURE__ */ import_react28.default.createElement("span", { className: "Layer__loader" }, /* @__PURE__ */ import_react28.default.createElement(Loader_default, { size: 14, className: "Layer__anim--rotating" }), children ?? "Loading...");
999
2207
  };
1000
2208
 
1001
2209
  // src/components/BankTransactions/BankTransactions.tsx
1002
- var dateFormat = "MM/dd/yyyy";
2210
+ var COMPONENT_NAME = "bank-transactions";
2211
+ var dateFormat = "LLL d, yyyy";
1003
2212
  var CategorizedCategories = [
1004
2213
  "CATEGORIZED" /* CATEGORIZED */,
1005
2214
  "JOURNALING" /* JOURNALING */,
@@ -1013,46 +2222,83 @@ var filterVisibility = (display) => (bankTransaction) => {
1013
2222
  const categorized = CategorizedCategories.includes(
1014
2223
  bankTransaction.categorization_status
1015
2224
  );
1016
- const inReview = ReviewCategories.includes(
1017
- bankTransaction.categorization_status
1018
- );
2225
+ const inReview = ReviewCategories.includes(bankTransaction.categorization_status) || bankTransaction.recently_categorized;
1019
2226
  return display === "review" /* review */ && inReview || display === "categorized" /* categorized */ && categorized;
1020
2227
  };
1021
2228
  var BankTransactions = () => {
1022
- const [display, setDisplay] = (0, import_react12.useState)("review" /* review */);
1023
- const { data } = useBankTransactions();
2229
+ const [display, setDisplay] = (0, import_react29.useState)("review" /* review */);
2230
+ const { data, isLoading } = useBankTransactions();
1024
2231
  const bankTransactions = data.filter(filterVisibility(display));
1025
2232
  const onCategorizationDisplayChange = (event) => setDisplay(
1026
2233
  event.target.value === "categorized" /* categorized */ ? "categorized" /* categorized */ : "review" /* review */
1027
2234
  );
1028
- const [openRows, setOpenRows] = (0, import_react12.useState)({});
2235
+ const [openRows, setOpenRows] = (0, import_react29.useState)({});
1029
2236
  const toggleOpen = (id) => setOpenRows({ ...openRows, [id]: !openRows[id] });
1030
- return /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions", "data-display": display }, /* @__PURE__ */ import_react12.default.createElement("header", { className: "Layer__bank-transactions__header" }, /* @__PURE__ */ import_react12.default.createElement("h2", { className: "Layer__bank-transactions__title" }, "Transactions"), /* @__PURE__ */ import_react12.default.createElement(
1031
- RadioButtonGroup,
1032
- {
1033
- name: "bank-transaction-display",
1034
- buttons: [
1035
- { label: "To Review", value: "review" /* review */ },
1036
- { label: "Categorized", value: "categorized" /* categorized */ }
1037
- ],
1038
- selected: display,
1039
- onChange: onCategorizationDisplayChange
2237
+ const [shiftStickyHeader, setShiftStickyHeader] = (0, import_react29.useState)(0);
2238
+ const headerRef = useElementSize((_el, _en, size) => {
2239
+ if (size?.height && size?.height >= 90) {
2240
+ const newShift = -Math.floor(size.height / 2) + 6;
2241
+ if (newShift !== shiftStickyHeader) {
2242
+ setShiftStickyHeader(newShift);
2243
+ }
2244
+ } else if (size?.height > 0 && shiftStickyHeader !== 0) {
2245
+ setShiftStickyHeader(0);
1040
2246
  }
1041
- )), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table" }, /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Date"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Transaction"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Account"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header Layer__bank-transactions__table-cell--header-amount" }, "Amount"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Category"), /* @__PURE__ */ import_react12.default.createElement("div", { className: "Layer__bank-transactions__table-cell Layer__bank-transactions__table-cell--header" }, "Actions"), bankTransactions.map((bankTransaction) => /* @__PURE__ */ import_react12.default.createElement(
1042
- BankTransactionRow,
2247
+ });
2248
+ const editable = display === "review" /* review */;
2249
+ return /* @__PURE__ */ import_react29.default.createElement(Container, { name: COMPONENT_NAME }, /* @__PURE__ */ import_react29.default.createElement(
2250
+ Header,
2251
+ {
2252
+ ref: headerRef,
2253
+ className: "Layer__bank-transactions__header",
2254
+ style: { top: shiftStickyHeader }
2255
+ },
2256
+ /* @__PURE__ */ import_react29.default.createElement(Heading, { className: "Layer__bank-transactions__title" }, "Transactions"),
2257
+ /* @__PURE__ */ import_react29.default.createElement(
2258
+ Toggle,
2259
+ {
2260
+ name: "bank-transaction-display",
2261
+ options: [
2262
+ { label: "To Review", value: "review" /* review */ },
2263
+ { label: "Categorized", value: "categorized" /* categorized */ }
2264
+ ],
2265
+ selected: display,
2266
+ onChange: onCategorizationDisplayChange
2267
+ }
2268
+ )
2269
+ ), /* @__PURE__ */ import_react29.default.createElement(
2270
+ "table",
2271
+ {
2272
+ width: "100%",
2273
+ className: "Layer__table Layer__bank-transactions__table"
2274
+ },
2275
+ /* @__PURE__ */ import_react29.default.createElement("thead", null, /* @__PURE__ */ import_react29.default.createElement("tr", null, /* @__PURE__ */ import_react29.default.createElement("th", { className: "Layer__table-header Layer__bank-transactions__date-col" }, "Date"), /* @__PURE__ */ import_react29.default.createElement("th", { className: "Layer__table-header Layer__bank-transactions__tx-col" }, "Transaction"), /* @__PURE__ */ import_react29.default.createElement("th", { className: "Layer__table-header Layer__bank-transactions__account-col" }, "Account"), /* @__PURE__ */ import_react29.default.createElement("th", { className: "Layer__table-header Layer__table-cell--amount Layer__table-cell__amount-col" }, "Amount"), editable ? /* @__PURE__ */ import_react29.default.createElement("th", { className: "Layer__table-header Layer__table-header--primary Layer__table-cell__category-col" }, "Categorize") : /* @__PURE__ */ import_react29.default.createElement("th", { className: "Layer__table-header Layer__table-cell__category-col" }, "Category"))),
2276
+ /* @__PURE__ */ import_react29.default.createElement("tbody", null, !isLoading && bankTransactions.map((bankTransaction) => /* @__PURE__ */ import_react29.default.createElement(
2277
+ BankTransactionRow,
2278
+ {
2279
+ key: bankTransaction.id,
2280
+ dateFormat,
2281
+ bankTransaction,
2282
+ isOpen: openRows[bankTransaction.id],
2283
+ toggleOpen,
2284
+ editable
2285
+ }
2286
+ )))
2287
+ ), isLoading || !bankTransactions || bankTransactions?.length === 0 ? /* @__PURE__ */ import_react29.default.createElement(Loader2, null) : null, !isLoading && /* @__PURE__ */ import_react29.default.createElement("ul", { className: "Layer__bank-transactions__list" }, bankTransactions.map((bankTransaction) => /* @__PURE__ */ import_react29.default.createElement(
2288
+ BankTransactionListItem,
1043
2289
  {
1044
2290
  key: bankTransaction.id,
1045
2291
  dateFormat,
1046
2292
  bankTransaction,
1047
2293
  isOpen: openRows[bankTransaction.id],
1048
2294
  toggleOpen,
1049
- editable: display === "review" /* review */
2295
+ editable
1050
2296
  }
1051
2297
  ))));
1052
2298
  };
1053
2299
 
1054
2300
  // src/components/Hello/Hello.tsx
1055
- var import_react13 = __toESM(require("react"));
2301
+ var import_react30 = __toESM(require("react"));
1056
2302
  var import_swr3 = __toESM(require("swr"));
1057
2303
  var fetcher = (url) => fetch(url).then((res) => res.json());
1058
2304
  var Hello = ({ user }) => {
@@ -1061,26 +2307,26 @@ var Hello = ({ user }) => {
1061
2307
  fetcher
1062
2308
  );
1063
2309
  const name = (isLoading ? "..." : data?.name) || "User";
1064
- return /* @__PURE__ */ import_react13.default.createElement(import_react13.default.Fragment, null, /* @__PURE__ */ import_react13.default.createElement("div", { className: "hello" }, "Hello, ", name, "!"));
2310
+ return /* @__PURE__ */ import_react30.default.createElement(import_react30.default.Fragment, null, /* @__PURE__ */ import_react30.default.createElement("div", { className: "hello" }, "Hello, ", name, "!"));
1065
2311
  };
1066
2312
 
1067
2313
  // src/components/ProfitAndLoss/ProfitAndLoss.tsx
1068
- var import_react21 = __toESM(require("react"));
2314
+ var import_react38 = __toESM(require("react"));
1069
2315
 
1070
2316
  // src/hooks/useProfitAndLoss/useProfitAndLoss.tsx
1071
- var import_react14 = require("react");
1072
- var import_date_fns5 = require("date-fns");
2317
+ var import_react31 = require("react");
2318
+ var import_date_fns6 = require("date-fns");
1073
2319
  var import_swr4 = __toESM(require("swr"));
1074
2320
  var useProfitAndLoss = ({ startDate: initialStartDate, endDate: initialEndDate } = {
1075
- startDate: (0, import_date_fns5.startOfMonth)(/* @__PURE__ */ new Date()),
1076
- endDate: (0, import_date_fns5.endOfMonth)(/* @__PURE__ */ new Date())
2321
+ startDate: (0, import_date_fns6.startOfMonth)(/* @__PURE__ */ new Date()),
2322
+ endDate: (0, import_date_fns6.endOfMonth)(/* @__PURE__ */ new Date())
1077
2323
  }) => {
1078
- const { auth, businessId } = useLayerContext();
1079
- const [startDate, setStartDate] = (0, import_react14.useState)(
1080
- initialStartDate || (0, import_date_fns5.startOfMonth)(Date.now())
2324
+ const { auth, businessId, apiUrl } = useLayerContext();
2325
+ const [startDate, setStartDate] = (0, import_react31.useState)(
2326
+ initialStartDate || (0, import_date_fns6.startOfMonth)(Date.now())
1081
2327
  );
1082
- const [endDate, setEndDate] = (0, import_react14.useState)(
1083
- initialEndDate || (0, import_date_fns5.endOfMonth)(Date.now())
2328
+ const [endDate, setEndDate] = (0, import_react31.useState)(
2329
+ initialEndDate || (0, import_date_fns6.endOfMonth)(Date.now())
1084
2330
  );
1085
2331
  const {
1086
2332
  data: rawData,
@@ -1088,11 +2334,11 @@ var useProfitAndLoss = ({ startDate: initialStartDate, endDate: initialEndDate }
1088
2334
  error: rawError
1089
2335
  } = (0, import_swr4.default)(
1090
2336
  businessId && startDate && endDate && auth?.access_token && `profit-and-loss-${businessId}-${startDate.valueOf()}-${endDate.valueOf()}`,
1091
- Layer.getProfitAndLoss(auth?.access_token, {
2337
+ Layer.getProfitAndLoss(apiUrl, auth?.access_token, {
1092
2338
  params: {
1093
2339
  businessId,
1094
- startDate: (0, import_date_fns5.formatISO)(startDate),
1095
- endDate: (0, import_date_fns5.formatISO)(endDate)
2340
+ startDate: (0, import_date_fns6.formatISO)(startDate),
2341
+ endDate: (0, import_date_fns6.formatISO)(endDate)
1096
2342
  }
1097
2343
  })
1098
2344
  );
@@ -1114,10 +2360,10 @@ var useProfitAndLoss = ({ startDate: initialStartDate, endDate: initialEndDate }
1114
2360
  };
1115
2361
 
1116
2362
  // src/components/ProfitAndLossChart/ProfitAndLossChart.tsx
1117
- var import_react16 = __toESM(require("react"));
2363
+ var import_react33 = __toESM(require("react"));
1118
2364
 
1119
2365
  // src/components/ProfitAndLossChart/Indicator.tsx
1120
- var import_react15 = __toESM(require("react"));
2366
+ var import_react32 = __toESM(require("react"));
1121
2367
  var emptyViewBox = { x: 0, y: 0, width: 0, height: 0 };
1122
2368
  var Indicator = ({
1123
2369
  viewBox = {},
@@ -1137,16 +2383,17 @@ var Indicator = ({
1137
2383
  const boxWidth = width * 2 + 4;
1138
2384
  const multiplier = 1.5;
1139
2385
  const xOffset = (boxWidth * multiplier - boxWidth) / 2;
1140
- (0, import_react15.useEffect)(() => {
2386
+ (0, import_react32.useEffect)(() => {
1141
2387
  setAnimateFrom(animateTo);
1142
2388
  }, [animateTo]);
1143
2389
  const actualX = animateFrom === -1 ? animateTo : animateFrom;
1144
- return /* @__PURE__ */ import_react15.default.createElement(
2390
+ return /* @__PURE__ */ import_react32.default.createElement(
1145
2391
  "rect",
1146
2392
  {
1147
2393
  className: "Layer__profit-and-loss-chart__selection-indicator",
1148
2394
  style: {
1149
2395
  width: `${boxWidth * multiplier}px`,
2396
+ // @ts-expect-error -- y is fine but x apparently isn't!
1150
2397
  x: actualX - xOffset,
1151
2398
  y: y + height
1152
2399
  }
@@ -1155,106 +2402,106 @@ var Indicator = ({
1155
2402
  };
1156
2403
 
1157
2404
  // src/components/ProfitAndLossChart/ProfitAndLossChart.tsx
1158
- var import_date_fns6 = require("date-fns");
2405
+ var import_date_fns7 = require("date-fns");
1159
2406
  var import_recharts = require("recharts");
1160
2407
  var barGap = 4;
1161
2408
  var barSize = 20;
1162
2409
  var ProfitAndLossChart = () => {
1163
- const { changeDateRange, dateRange } = (0, import_react16.useContext)(ProfitAndLoss.Context);
1164
- const thisMonth = (0, import_date_fns6.startOfMonth)(Date.now());
2410
+ const { changeDateRange, dateRange } = (0, import_react33.useContext)(ProfitAndLoss.Context);
2411
+ const thisMonth = (0, import_date_fns7.startOfMonth)(Date.now());
1165
2412
  const startSelectionMonth = dateRange.startDate.getMonth();
1166
2413
  const endSelectionMonth = dateRange.endDate.getMonth();
1167
2414
  const monthData = [];
1168
2415
  monthData.push(
1169
2416
  useProfitAndLoss({
1170
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 11 })),
1171
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 11 }))
2417
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 11 })),
2418
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 11 }))
1172
2419
  })?.data
1173
2420
  );
1174
2421
  monthData.push(
1175
2422
  useProfitAndLoss({
1176
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 10 })),
1177
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 10 }))
2423
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 10 })),
2424
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 10 }))
1178
2425
  })?.data
1179
2426
  );
1180
2427
  monthData.push(
1181
2428
  useProfitAndLoss({
1182
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 9 })),
1183
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 9 }))
2429
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 9 })),
2430
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 9 }))
1184
2431
  })?.data
1185
2432
  );
1186
2433
  monthData.push(
1187
2434
  useProfitAndLoss({
1188
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 8 })),
1189
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 8 }))
2435
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 8 })),
2436
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 8 }))
1190
2437
  })?.data
1191
2438
  );
1192
2439
  monthData.push(
1193
2440
  useProfitAndLoss({
1194
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 7 })),
1195
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 7 }))
2441
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 7 })),
2442
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 7 }))
1196
2443
  })?.data
1197
2444
  );
1198
2445
  monthData.push(
1199
2446
  useProfitAndLoss({
1200
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 6 })),
1201
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 6 }))
2447
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 6 })),
2448
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 6 }))
1202
2449
  })?.data
1203
2450
  );
1204
2451
  monthData.push(
1205
2452
  useProfitAndLoss({
1206
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 5 })),
1207
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 5 }))
2453
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 5 })),
2454
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 5 }))
1208
2455
  })?.data
1209
2456
  );
1210
2457
  monthData.push(
1211
2458
  useProfitAndLoss({
1212
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 4 })),
1213
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 4 }))
2459
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 4 })),
2460
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 4 }))
1214
2461
  })?.data
1215
2462
  );
1216
2463
  monthData.push(
1217
2464
  useProfitAndLoss({
1218
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 3 })),
1219
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 3 }))
2465
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 3 })),
2466
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 3 }))
1220
2467
  })?.data
1221
2468
  );
1222
2469
  monthData.push(
1223
2470
  useProfitAndLoss({
1224
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 2 })),
1225
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 2 }))
2471
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 2 })),
2472
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 2 }))
1226
2473
  })?.data
1227
2474
  );
1228
2475
  monthData.push(
1229
2476
  useProfitAndLoss({
1230
- startDate: (0, import_date_fns6.startOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 1 })),
1231
- endDate: (0, import_date_fns6.endOfMonth)((0, import_date_fns6.sub)(thisMonth, { months: 1 }))
2477
+ startDate: (0, import_date_fns7.startOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 1 })),
2478
+ endDate: (0, import_date_fns7.endOfMonth)((0, import_date_fns7.sub)(thisMonth, { months: 1 }))
1232
2479
  })?.data
1233
2480
  );
1234
2481
  monthData.push(
1235
2482
  useProfitAndLoss({
1236
2483
  startDate: thisMonth,
1237
- endDate: (0, import_date_fns6.endOfMonth)(thisMonth)
2484
+ endDate: (0, import_date_fns7.endOfMonth)(thisMonth)
1238
2485
  })?.data
1239
2486
  );
1240
- const getMonthName = (pnl) => !!pnl ? (0, import_date_fns6.format)((0, import_date_fns6.parseISO)(pnl.start_date), "LLL") : "";
2487
+ const getMonthName = (pnl) => pnl ? (0, import_date_fns7.format)((0, import_date_fns7.parseISO)(pnl.start_date), "LLL") : "";
1241
2488
  const summarizePnL = (pnl) => ({
1242
2489
  name: getMonthName(pnl),
1243
2490
  revenue: pnl?.income.value || 0,
1244
2491
  expenses: (pnl?.income.value || 0) - (pnl?.net_profit || 0),
1245
- selected: !!pnl && (0, import_date_fns6.parseISO)(pnl.start_date).getMonth() >= startSelectionMonth && (0, import_date_fns6.parseISO)(pnl.end_date).getMonth() <= endSelectionMonth
2492
+ selected: !!pnl && (0, import_date_fns7.parseISO)(pnl.start_date).getMonth() >= startSelectionMonth && (0, import_date_fns7.parseISO)(pnl.end_date).getMonth() <= endSelectionMonth
1246
2493
  });
1247
2494
  const onClick = ({ activeTooltipIndex }) => {
1248
2495
  const selection = monthData[activeTooltipIndex || -1];
1249
2496
  if (selection) {
1250
2497
  const { start_date: startDate, end_date: endDate } = selection;
1251
2498
  changeDateRange({
1252
- startDate: (0, import_date_fns6.parseISO)(startDate),
1253
- endDate: (0, import_date_fns6.parseISO)(endDate)
2499
+ startDate: (0, import_date_fns7.parseISO)(startDate),
2500
+ endDate: (0, import_date_fns7.parseISO)(endDate)
1254
2501
  });
1255
2502
  }
1256
2503
  };
1257
- const data = (0, import_react16.useMemo)(
2504
+ const data = (0, import_react33.useMemo)(
1258
2505
  () => monthData.map(summarizePnL),
1259
2506
  [
1260
2507
  startSelectionMonth,
@@ -1262,8 +2509,8 @@ var ProfitAndLossChart = () => {
1262
2509
  ...monthData.map((m) => m?.net_profit)
1263
2510
  ]
1264
2511
  );
1265
- const [animateFrom, setAnimateFrom] = (0, import_react16.useState)(-1);
1266
- return /* @__PURE__ */ import_react16.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: 250 }, /* @__PURE__ */ import_react16.default.createElement(
2512
+ const [animateFrom, setAnimateFrom] = (0, import_react33.useState)(-1);
2513
+ return /* @__PURE__ */ import_react33.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: 250 }, /* @__PURE__ */ import_react33.default.createElement(
1267
2514
  import_recharts.BarChart,
1268
2515
  {
1269
2516
  margin: { left: 24, right: 24, bottom: 24 },
@@ -1272,8 +2519,8 @@ var ProfitAndLossChart = () => {
1272
2519
  barGap,
1273
2520
  className: "Layer__profit-and-loss-chart"
1274
2521
  },
1275
- /* @__PURE__ */ import_react16.default.createElement(import_recharts.CartesianGrid, { vertical: false }),
1276
- /* @__PURE__ */ import_react16.default.createElement(
2522
+ /* @__PURE__ */ import_react33.default.createElement(import_recharts.CartesianGrid, { vertical: false }),
2523
+ /* @__PURE__ */ import_react33.default.createElement(
1277
2524
  import_recharts.Legend,
1278
2525
  {
1279
2526
  verticalAlign: "top",
@@ -1284,8 +2531,8 @@ var ProfitAndLossChart = () => {
1284
2531
  ]
1285
2532
  }
1286
2533
  ),
1287
- /* @__PURE__ */ import_react16.default.createElement(import_recharts.XAxis, { dataKey: "name", tickLine: false }),
1288
- /* @__PURE__ */ import_react16.default.createElement(
2534
+ /* @__PURE__ */ import_react33.default.createElement(import_recharts.XAxis, { dataKey: "name", tickLine: false }),
2535
+ /* @__PURE__ */ import_react33.default.createElement(
1289
2536
  import_recharts.Bar,
1290
2537
  {
1291
2538
  dataKey: "revenue",
@@ -1294,10 +2541,10 @@ var ProfitAndLossChart = () => {
1294
2541
  radius: [barSize / 4, barSize / 4, 0, 0],
1295
2542
  className: "Layer__profit-and-loss-chart__bar--income"
1296
2543
  },
1297
- /* @__PURE__ */ import_react16.default.createElement(
2544
+ /* @__PURE__ */ import_react33.default.createElement(
1298
2545
  import_recharts.LabelList,
1299
2546
  {
1300
- content: /* @__PURE__ */ import_react16.default.createElement(
2547
+ content: /* @__PURE__ */ import_react33.default.createElement(
1301
2548
  Indicator,
1302
2549
  {
1303
2550
  animateFrom,
@@ -1306,7 +2553,7 @@ var ProfitAndLossChart = () => {
1306
2553
  )
1307
2554
  }
1308
2555
  ),
1309
- data.map((entry) => /* @__PURE__ */ import_react16.default.createElement(
2556
+ data.map((entry) => /* @__PURE__ */ import_react33.default.createElement(
1310
2557
  import_recharts.Cell,
1311
2558
  {
1312
2559
  key: entry.name,
@@ -1314,7 +2561,7 @@ var ProfitAndLossChart = () => {
1314
2561
  }
1315
2562
  ))
1316
2563
  ),
1317
- /* @__PURE__ */ import_react16.default.createElement(
2564
+ /* @__PURE__ */ import_react33.default.createElement(
1318
2565
  import_recharts.Bar,
1319
2566
  {
1320
2567
  dataKey: "expenses",
@@ -1323,7 +2570,7 @@ var ProfitAndLossChart = () => {
1323
2570
  radius: [barSize / 4, barSize / 4, 0, 0],
1324
2571
  className: "Layer__profit-and-loss-chart__bar--expenses"
1325
2572
  },
1326
- data.map((entry) => /* @__PURE__ */ import_react16.default.createElement(
2573
+ data.map((entry) => /* @__PURE__ */ import_react33.default.createElement(
1327
2574
  import_recharts.Cell,
1328
2575
  {
1329
2576
  key: entry.name,
@@ -1335,15 +2582,15 @@ var ProfitAndLossChart = () => {
1335
2582
  };
1336
2583
 
1337
2584
  // src/components/ProfitAndLossDatePicker/ProfitAndLossDatePicker.tsx
1338
- var import_react17 = __toESM(require("react"));
2585
+ var import_react34 = __toESM(require("react"));
1339
2586
 
1340
2587
  // src/icons/ChevronLeft.tsx
1341
- var React22 = __toESM(require("react"));
2588
+ var React40 = __toESM(require("react"));
1342
2589
  var ChevronLeft = ({
1343
2590
  strokeColor,
1344
2591
  size,
1345
2592
  ...props
1346
- }) => /* @__PURE__ */ React22.createElement(
2593
+ }) => /* @__PURE__ */ React40.createElement(
1347
2594
  "svg",
1348
2595
  {
1349
2596
  xmlns: "http://www.w3.org/2000/svg",
@@ -1353,7 +2600,7 @@ var ChevronLeft = ({
1353
2600
  viewBox: "0 0 24 24",
1354
2601
  ...props
1355
2602
  },
1356
- /* @__PURE__ */ React22.createElement(
2603
+ /* @__PURE__ */ React40.createElement(
1357
2604
  "path",
1358
2605
  {
1359
2606
  stroke: strokeColor ?? "#000",
@@ -1366,43 +2613,68 @@ var ChevronLeft = ({
1366
2613
  );
1367
2614
  var ChevronLeft_default = ChevronLeft;
1368
2615
 
2616
+ // src/icons/ChevronRight.tsx
2617
+ var React41 = __toESM(require("react"));
2618
+ var ChavronRight = ({ size, ...props }) => /* @__PURE__ */ React41.createElement(
2619
+ "svg",
2620
+ {
2621
+ xmlns: "http://www.w3.org/2000/svg",
2622
+ width: size || 24,
2623
+ height: size || 24,
2624
+ fill: "none",
2625
+ viewBox: "0 0 24 24",
2626
+ ...props
2627
+ },
2628
+ /* @__PURE__ */ React41.createElement(
2629
+ "path",
2630
+ {
2631
+ stroke: "#000",
2632
+ strokeLinecap: "round",
2633
+ strokeLinejoin: "round",
2634
+ strokeWidth: 2,
2635
+ d: "m9 18 6-6-6-6"
2636
+ }
2637
+ )
2638
+ );
2639
+ var ChevronRight_default = ChavronRight;
2640
+
1369
2641
  // src/components/ProfitAndLossDatePicker/ProfitAndLossDatePicker.tsx
1370
- var import_date_fns7 = require("date-fns");
2642
+ var import_date_fns8 = require("date-fns");
1371
2643
  var ProfitAndLossDatePicker = () => {
1372
- const { changeDateRange, dateRange } = (0, import_react17.useContext)(ProfitAndLoss.Context);
2644
+ const { changeDateRange, dateRange } = (0, import_react34.useContext)(ProfitAndLoss.Context);
1373
2645
  const date = dateRange.startDate;
1374
- const label = (0, import_date_fns7.format)(date, "LLLL y");
2646
+ const label = (0, import_date_fns8.format)(date, "LLLL y");
1375
2647
  const change = (duration) => {
1376
- const newDate = (0, import_date_fns7.add)(date, duration);
2648
+ const newDate = (0, import_date_fns8.add)(date, duration);
1377
2649
  changeDateRange({
1378
- startDate: (0, import_date_fns7.startOfMonth)(newDate),
1379
- endDate: (0, import_date_fns7.endOfMonth)(newDate)
2650
+ startDate: (0, import_date_fns8.startOfMonth)(newDate),
2651
+ endDate: (0, import_date_fns8.endOfMonth)(newDate)
1380
2652
  });
1381
2653
  };
1382
2654
  const previousMonth = () => change({ months: -1 });
1383
2655
  const nextMonth = () => change({ months: 1 });
1384
- return /* @__PURE__ */ import_react17.default.createElement("div", { className: "Layer__profit-and-loss-date-picker" }, /* @__PURE__ */ import_react17.default.createElement(
2656
+ return /* @__PURE__ */ import_react34.default.createElement("div", { className: "Layer__profit-and-loss-date-picker" }, /* @__PURE__ */ import_react34.default.createElement(
1385
2657
  "button",
1386
2658
  {
1387
2659
  "aria-label": "View Previous Month",
1388
2660
  className: "Layer__profit-and-loss-date-picker__button",
1389
2661
  onClick: previousMonth
1390
2662
  },
1391
- /* @__PURE__ */ import_react17.default.createElement(
2663
+ /* @__PURE__ */ import_react34.default.createElement(
1392
2664
  ChevronLeft_default,
1393
2665
  {
1394
2666
  className: "Layer__profit-and-loss-date-picker__button-icon",
1395
2667
  size: 18
1396
2668
  }
1397
2669
  )
1398
- ), /* @__PURE__ */ import_react17.default.createElement("span", { className: "Layer__profit-and-loss-date-picker__label" }, label), /* @__PURE__ */ import_react17.default.createElement(
2670
+ ), /* @__PURE__ */ import_react34.default.createElement("span", { className: "Layer__profit-and-loss-date-picker__label" }, label), /* @__PURE__ */ import_react34.default.createElement(
1399
2671
  "button",
1400
2672
  {
1401
2673
  "aria-label": "View Next Month",
1402
2674
  className: "Layer__profit-and-loss-date-picker__button",
1403
2675
  onClick: nextMonth
1404
2676
  },
1405
- /* @__PURE__ */ import_react17.default.createElement(
2677
+ /* @__PURE__ */ import_react34.default.createElement(
1406
2678
  ChevronRight_default,
1407
2679
  {
1408
2680
  className: "Layer__profit-and-loss-date-picker__button-icon",
@@ -1413,35 +2685,53 @@ var ProfitAndLossDatePicker = () => {
1413
2685
  };
1414
2686
 
1415
2687
  // src/components/ProfitAndLossSummaries/ProfitAndLossSummaries.tsx
1416
- var import_react18 = __toESM(require("react"));
1417
- var import_date_fns8 = require("date-fns");
2688
+ var import_react35 = __toESM(require("react"));
1418
2689
  var ProfitAndLossSummaries = () => {
1419
- const { data } = (0, import_react18.useContext)(ProfitAndLoss.Context);
1420
- if (!data) {
1421
- return null;
1422
- }
1423
- const monthName = (0, import_date_fns8.format)((0, import_date_fns8.parseISO)(data?.start_date), "LLLL");
1424
- return /* @__PURE__ */ import_react18.default.createElement("div", { className: "Layer__profit-and-loss-summaries" }, /* @__PURE__ */ import_react18.default.createElement("div", { className: "Layer__profit-and-loss-summaries__summary Layer__profit-and-loss-summaries__summary--income" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Revenue"), /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__amount" }, centsToDollars(data.income.value))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "Layer__profit-and-loss-summaries__summary Layer__profit-and-loss-summaries__summary--expenses" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Expenses"), /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__amount" }, centsToDollars(Math.abs(data.income.value - data.net_profit)))), /* @__PURE__ */ import_react18.default.createElement("div", { className: "Layer__profit-and-loss-summaries__summary Layer__profit-and-loss-summaries__summary--net-profit" }, /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Net Profit"), /* @__PURE__ */ import_react18.default.createElement("span", { className: "Layer__profit-and-loss-summaries__amount" }, centsToDollars(data.net_profit))));
2690
+ const { data: storedData } = (0, import_react35.useContext)(ProfitAndLoss.Context);
2691
+ const data = storedData ? storedData : { income: { value: NaN }, net_profit: NaN };
2692
+ const incomeDirectionClass = (data.income.value ?? NaN) < 0 ? "Layer__profit-and-loss-summaries__amount--negative" : "Layer__profit-and-loss-summaries__amount--pasitive";
2693
+ const expensesDirectionClass = (data?.income?.value ?? NaN) - data.net_profit < 0 ? "Layer__profit-and-loss-summaries__amount--negative" : "Layer__profit-and-loss-summaries__amount--pasitive";
2694
+ const netProfitDirectionClass = data.net_profit < 0 ? "Layer__profit-and-loss-summaries__amount--negative" : "Layer__profit-and-loss-summaries__amount--pasitive";
2695
+ return /* @__PURE__ */ import_react35.default.createElement("div", { className: "Layer__profit-and-loss-summaries" }, /* @__PURE__ */ import_react35.default.createElement("div", { className: "Layer__profit-and-loss-summaries__summary Layer__profit-and-loss-summaries__summary--income" }, /* @__PURE__ */ import_react35.default.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Revenue"), /* @__PURE__ */ import_react35.default.createElement(
2696
+ "span",
2697
+ {
2698
+ className: `Layer__profit-and-loss-summaries__amount ${incomeDirectionClass}`
2699
+ },
2700
+ centsToDollars(Math.abs(data?.income?.value ?? NaN))
2701
+ )), /* @__PURE__ */ import_react35.default.createElement("div", { className: "Layer__profit-and-loss-summaries__summary Layer__profit-and-loss-summaries__summary--expenses" }, /* @__PURE__ */ import_react35.default.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Expenses"), /* @__PURE__ */ import_react35.default.createElement(
2702
+ "span",
2703
+ {
2704
+ className: `Layer__profit-and-loss-summaries__amount ${expensesDirectionClass}`
2705
+ },
2706
+ centsToDollars(Math.abs((data.income.value ?? 0) - data.net_profit))
2707
+ )), /* @__PURE__ */ import_react35.default.createElement("div", { className: "Layer__profit-and-loss-summaries__summary Layer__profit-and-loss-summaries__summary--net-profit" }, /* @__PURE__ */ import_react35.default.createElement("span", { className: "Layer__profit-and-loss-summaries__title" }, "Net Profit"), /* @__PURE__ */ import_react35.default.createElement(
2708
+ "span",
2709
+ {
2710
+ className: `Layer__profit-and-loss-summaries__amount ${netProfitDirectionClass}`
2711
+ },
2712
+ centsToDollars(Math.abs(data.net_profit))
2713
+ )));
1425
2714
  };
1426
2715
 
1427
2716
  // src/components/ProfitAndLossTable/ProfitAndLossTable.tsx
1428
- var import_react20 = __toESM(require("react"));
2717
+ var import_react37 = __toESM(require("react"));
1429
2718
 
1430
2719
  // src/components/ProfitAndLossRow/ProfitAndLossRow.tsx
1431
- var import_react19 = __toESM(require("react"));
2720
+ var import_react36 = __toESM(require("react"));
1432
2721
  var ProfitAndLossRow = ({
1433
2722
  variant,
1434
2723
  lineItem,
1435
2724
  depth = 0,
1436
2725
  maxDepth = 1,
1437
- direction = "DEBIT" /* DEBIT */
2726
+ direction = "DEBIT" /* DEBIT */,
2727
+ summarize = true
1438
2728
  }) => {
1439
2729
  if (!lineItem) {
1440
2730
  return null;
1441
2731
  }
1442
- const { value, display_name, line_items, name } = lineItem;
1443
- const variantName = variant || name;
1444
- const amount = value || 0;
2732
+ const { value, display_name, line_items } = lineItem;
2733
+ const [expanded, setExpanded] = (0, import_react36.useState)(true);
2734
+ const amount = value ?? 0;
1445
2735
  const amountString = centsToDollars(Math.abs(amount));
1446
2736
  const labelClasses = [
1447
2737
  "Layer__profit-and-loss-row",
@@ -1451,87 +2741,154 @@ var ProfitAndLossRow = ({
1451
2741
  "Layer__profit-and-loss-row",
1452
2742
  "Layer__profit-and-loss-row__value"
1453
2743
  ];
2744
+ const positive = amount === 0 || direction === "CREDIT" /* CREDIT */ && amount > 0 || direction === "DEBIT" /* DEBIT */ && amount < 0;
1454
2745
  valueClasses.push(
1455
- direction === "CREDIT" /* CREDIT */ ? "Layer__profit-and-loss-row__value--amount-positive" : "Layer__profit-and-loss-row__value--amount-negative"
2746
+ positive ? "Layer__profit-and-loss-row__value--amount-positive" : "Layer__profit-and-loss-row__value--amount-negative"
1456
2747
  );
1457
2748
  labelClasses.push(`Layer__profit-and-loss-row__label--depth-${depth}`);
1458
2749
  valueClasses.push(`Layer__profit-and-loss-row__value--depth-${depth}`);
1459
- variantName && labelClasses.push(
1460
- `Layer__profit-and-loss-row__label--variant-${variantName}`
2750
+ variant && labelClasses.push(`Layer__profit-and-loss-row__label--variant-${variant}`);
2751
+ variant && valueClasses.push(`Layer__profit-and-loss-row__value--variant-${variant}`);
2752
+ const toggleExpanded = () => setExpanded(!expanded);
2753
+ const canGoDeeper = depth < maxDepth;
2754
+ const hasChildren = (line_items?.length ?? 0) > 0;
2755
+ const displayChildren = hasChildren && canGoDeeper;
2756
+ labelClasses.push(
2757
+ `Layer__profit-and-loss-row__label--display-children-${displayChildren}`
1461
2758
  );
1462
- variantName && valueClasses.push(
1463
- `Layer__profit-and-loss-row__value--variant-${variantName}`
2759
+ valueClasses.push(
2760
+ `Layer__profit-and-loss-row__value--display-children-${displayChildren}`
1464
2761
  );
1465
- return /* @__PURE__ */ import_react19.default.createElement(import_react19.default.Fragment, null, /* @__PURE__ */ import_react19.default.createElement("div", { className: labelClasses.join(" ") }, display_name), /* @__PURE__ */ import_react19.default.createElement("div", { className: valueClasses.join(" ") }, amountString), depth < maxDepth && (line_items || []).map((line_item) => /* @__PURE__ */ import_react19.default.createElement(
1466
- ProfitAndLossRow,
2762
+ displayChildren && expanded && labelClasses.push("Layer__profit-and-loss-row__label--expanded");
2763
+ displayChildren && expanded && valueClasses.push("Layer__profit-and-loss-row__value--expanded");
2764
+ return /* @__PURE__ */ import_react36.default.createElement(import_react36.default.Fragment, null, /* @__PURE__ */ import_react36.default.createElement("div", { className: labelClasses.join(" "), onClick: toggleExpanded }, /* @__PURE__ */ import_react36.default.createElement(ChevronDown_default, { size: 16 }), display_name), /* @__PURE__ */ import_react36.default.createElement("div", { className: valueClasses.join(" ") }, amountString), canGoDeeper && hasChildren && /* @__PURE__ */ import_react36.default.createElement(
2765
+ "div",
1467
2766
  {
1468
- key: line_item.display_name,
1469
- lineItem: line_item,
1470
- depth: depth + 1,
1471
- maxDepth,
1472
- direction
1473
- }
1474
- )));
2767
+ className: `Layer__profit-and-loss-row__children ${expanded && "Layer__profit-and-loss-row__children--expanded"}`
2768
+ },
2769
+ /* @__PURE__ */ import_react36.default.createElement("div", { className: "Layer__balance-sheet-row__children--content" }, (line_items || []).map((line_item) => /* @__PURE__ */ import_react36.default.createElement(
2770
+ ProfitAndLossRow,
2771
+ {
2772
+ key: line_item.display_name,
2773
+ lineItem: line_item,
2774
+ depth: depth + 1,
2775
+ maxDepth,
2776
+ direction
2777
+ }
2778
+ )), summarize && /* @__PURE__ */ import_react36.default.createElement(
2779
+ ProfitAndLossRow,
2780
+ {
2781
+ key: display_name,
2782
+ lineItem: { value, display_name: `Total of ${display_name}` },
2783
+ variant: "summation",
2784
+ depth: depth + 1,
2785
+ maxDepth
2786
+ }
2787
+ ))
2788
+ ));
2789
+ };
2790
+
2791
+ // src/components/ProfitAndLossTable/empty_profit_and_loss_report.ts
2792
+ var empty_profit_and_loss_report_default = {
2793
+ type: "Profit_And_Loss",
2794
+ business_id: "",
2795
+ start_date: "",
2796
+ end_date: "",
2797
+ income: {
2798
+ name: "INCOME",
2799
+ display_name: "Income",
2800
+ value: NaN,
2801
+ line_items: null
2802
+ },
2803
+ cost_of_goods_sold: {
2804
+ display_name: "Cost of Goods Sold",
2805
+ name: "COGS",
2806
+ value: NaN,
2807
+ line_items: null
2808
+ },
2809
+ gross_profit: NaN,
2810
+ expenses: {
2811
+ name: "EXPENSES",
2812
+ display_name: "Expenses",
2813
+ value: NaN,
2814
+ line_items: null
2815
+ },
2816
+ profit_before_taxes: NaN,
2817
+ taxes: {
2818
+ name: "TAXES",
2819
+ display_name: "Taxes",
2820
+ value: NaN,
2821
+ line_items: null
2822
+ },
2823
+ net_profit: NaN,
2824
+ other_outflows: {
2825
+ name: "OTHER_OUTFLOWS",
2826
+ display_name: "Other outflows",
2827
+ value: NaN,
2828
+ line_items: null
2829
+ },
2830
+ personal_expenses: {
2831
+ name: "PERSONAL",
2832
+ display_name: "Personal expenses",
2833
+ value: NaN,
2834
+ line_items: null
2835
+ },
2836
+ fully_categorized: false
1475
2837
  };
1476
2838
 
1477
2839
  // src/components/ProfitAndLossTable/ProfitAndLossTable.tsx
1478
2840
  var ProfitAndLossTable = () => {
1479
- const { data, isLoading } = (0, import_react20.useContext)(ProfitAndLoss.Context);
1480
- return /* @__PURE__ */ import_react20.default.createElement("div", { className: "Layer__profit-and-loss-table" }, !data || isLoading ? /* @__PURE__ */ import_react20.default.createElement("div", null, "Loading") : /* @__PURE__ */ import_react20.default.createElement(import_react20.default.Fragment, null, /* @__PURE__ */ import_react20.default.createElement(
1481
- ProfitAndLossRow,
1482
- {
1483
- lineItem: data.income,
1484
- direction: "CREDIT" /* CREDIT */
1485
- }
1486
- ), /* @__PURE__ */ import_react20.default.createElement(
2841
+ const { data: actualData, isLoading } = (0, import_react37.useContext)(ProfitAndLoss.Context);
2842
+ const data = !actualData || isLoading ? empty_profit_and_loss_report_default : actualData;
2843
+ return /* @__PURE__ */ import_react37.default.createElement(import_react37.default.Fragment, null, /* @__PURE__ */ import_react37.default.createElement("div", { className: "Layer__profit-and-loss-table" }, /* @__PURE__ */ import_react37.default.createElement(ProfitAndLossRow, { lineItem: data.income, direction: "CREDIT" /* CREDIT */ }), /* @__PURE__ */ import_react37.default.createElement(
1487
2844
  ProfitAndLossRow,
1488
2845
  {
1489
2846
  lineItem: data.cost_of_goods_sold,
1490
2847
  direction: "DEBIT" /* DEBIT */
1491
2848
  }
1492
- ), /* @__PURE__ */ import_react20.default.createElement(
2849
+ ), /* @__PURE__ */ import_react37.default.createElement(
1493
2850
  ProfitAndLossRow,
1494
2851
  {
1495
2852
  lineItem: {
1496
2853
  value: data.gross_profit,
1497
2854
  display_name: "Gross Profit"
1498
2855
  },
1499
- variant: "GROSS",
2856
+ variant: "summation",
1500
2857
  direction: "CREDIT" /* CREDIT */
1501
2858
  }
1502
- ), /* @__PURE__ */ import_react20.default.createElement(
2859
+ ), /* @__PURE__ */ import_react37.default.createElement(
1503
2860
  ProfitAndLossRow,
1504
2861
  {
1505
2862
  lineItem: data.expenses,
1506
2863
  direction: "DEBIT" /* DEBIT */
1507
2864
  }
1508
- ), /* @__PURE__ */ import_react20.default.createElement(
2865
+ ), /* @__PURE__ */ import_react37.default.createElement(
1509
2866
  ProfitAndLossRow,
1510
2867
  {
1511
2868
  lineItem: {
1512
2869
  value: data.profit_before_taxes,
1513
2870
  display_name: "Profit Before Taxes"
1514
2871
  },
1515
- variant: "BEFORETAX",
2872
+ variant: "summation",
1516
2873
  direction: "CREDIT" /* CREDIT */
1517
2874
  }
1518
- ), /* @__PURE__ */ import_react20.default.createElement(ProfitAndLossRow, { lineItem: data.taxes, direction: "DEBIT" /* DEBIT */ }), /* @__PURE__ */ import_react20.default.createElement(
2875
+ ), /* @__PURE__ */ import_react37.default.createElement(ProfitAndLossRow, { lineItem: data.taxes, direction: "DEBIT" /* DEBIT */ }), /* @__PURE__ */ import_react37.default.createElement(
1519
2876
  ProfitAndLossRow,
1520
2877
  {
1521
2878
  lineItem: {
1522
2879
  value: data.net_profit,
1523
2880
  display_name: "Net Profit"
1524
2881
  },
1525
- variant: "NETPROFIT",
2882
+ variant: "summation",
1526
2883
  direction: "CREDIT" /* CREDIT */
1527
2884
  }
1528
- ), /* @__PURE__ */ import_react20.default.createElement(
2885
+ )), /* @__PURE__ */ import_react37.default.createElement("div", { className: "Layer__profit-and-loss-table Layer__profit-and-loss-table__outflows" }, /* @__PURE__ */ import_react37.default.createElement(
1529
2886
  ProfitAndLossRow,
1530
2887
  {
1531
2888
  lineItem: data.other_outflows,
1532
2889
  direction: "DEBIT" /* DEBIT */
1533
2890
  }
1534
- ), /* @__PURE__ */ import_react20.default.createElement(
2891
+ ), /* @__PURE__ */ import_react37.default.createElement(
1535
2892
  ProfitAndLossRow,
1536
2893
  {
1537
2894
  lineItem: data.personal_expenses,
@@ -1542,7 +2899,7 @@ var ProfitAndLossTable = () => {
1542
2899
 
1543
2900
  // src/components/ProfitAndLoss/ProfitAndLoss.tsx
1544
2901
  var import_date_fns9 = require("date-fns");
1545
- var PNLContext = (0, import_react21.createContext)({
2902
+ var PNLContext = (0, import_react38.createContext)({
1546
2903
  data: void 0,
1547
2904
  isLoading: true,
1548
2905
  error: void 0,
@@ -1555,7 +2912,7 @@ var PNLContext = (0, import_react21.createContext)({
1555
2912
  });
1556
2913
  var ProfitAndLoss = ({ children }) => {
1557
2914
  const contextData = useProfitAndLoss();
1558
- return /* @__PURE__ */ import_react21.default.createElement(PNLContext.Provider, { value: contextData }, /* @__PURE__ */ import_react21.default.createElement("div", { className: "Layer__profit-and-loss" }, /* @__PURE__ */ import_react21.default.createElement("h2", { className: "Layer__profit-and-loss__title" }, "Profit & Loss"), children));
2915
+ return /* @__PURE__ */ import_react38.default.createElement(PNLContext.Provider, { value: contextData }, /* @__PURE__ */ import_react38.default.createElement("div", { className: "Layer__component Layer__profit-and-loss" }, /* @__PURE__ */ import_react38.default.createElement("h2", { className: "Layer__profit-and-loss__title" }, "Profit & Loss"), children));
1559
2916
  };
1560
2917
  ProfitAndLoss.Chart = ProfitAndLossChart;
1561
2918
  ProfitAndLoss.Context = PNLContext;
@@ -1564,12 +2921,14 @@ ProfitAndLoss.Summaries = ProfitAndLossSummaries;
1564
2921
  ProfitAndLoss.Table = ProfitAndLossTable;
1565
2922
 
1566
2923
  // src/providers/LayerProvider/LayerProvider.tsx
1567
- var import_react22 = __toESM(require("react"));
2924
+ var import_react39 = __toESM(require("react"));
2925
+ var import_date_fns10 = require("date-fns");
1568
2926
  var import_swr5 = __toESM(require("swr"));
1569
2927
  var reducer = (state, action) => {
1570
2928
  switch (action.type) {
1571
2929
  case "LayerContext.setAuth" /* setAuth */:
1572
2930
  case "LayerContext.setCategories" /* setCategories */:
2931
+ case "LayerContext.setTheme" /* setTheme */:
1573
2932
  return { ...state, ...action.payload };
1574
2933
  default:
1575
2934
  return state;
@@ -1578,11 +2937,13 @@ var reducer = (state, action) => {
1578
2937
  var LayerEnvironment = {
1579
2938
  production: {
1580
2939
  url: "not defined yet",
1581
- scope: "not defined yet"
2940
+ scope: "not defined yet",
2941
+ apiUrl: "not defined yet"
1582
2942
  },
1583
2943
  staging: {
1584
2944
  url: "https://auth.layerfi.com/oauth2/token",
1585
- scope: "https://sandbox.layerfi.com/sandbox"
2945
+ scope: "https://sandbox.layerfi.com/sandbox",
2946
+ apiUrl: "https://sandbox.layerfi.com"
1586
2947
  }
1587
2948
  };
1588
2949
  var LayerProvider = ({
@@ -1591,7 +2952,8 @@ var LayerProvider = ({
1591
2952
  businessId,
1592
2953
  children,
1593
2954
  clientId,
1594
- environment = "production"
2955
+ environment = "production",
2956
+ theme
1595
2957
  }) => {
1596
2958
  const defaultSWRConfig = {
1597
2959
  revalidateInterval: 0,
@@ -1599,14 +2961,21 @@ var LayerProvider = ({
1599
2961
  revalidateOnReconnect: false,
1600
2962
  revalidateIfStale: false
1601
2963
  };
1602
- const { url, scope } = LayerEnvironment[environment];
1603
- const [state, dispatch] = (0, import_react22.useReducer)(reducer, {
1604
- auth: { access_token: "", token_type: "", expires_in: 0 },
2964
+ const { url, scope, apiUrl } = LayerEnvironment[environment];
2965
+ const [state, dispatch] = (0, import_react39.useReducer)(reducer, {
2966
+ auth: {
2967
+ access_token: "",
2968
+ token_type: "",
2969
+ expires_in: 0,
2970
+ expires_at: new Date(2e3, 1, 1)
2971
+ },
1605
2972
  businessId,
1606
- categories: []
2973
+ categories: [],
2974
+ apiUrl,
2975
+ theme
1607
2976
  });
1608
2977
  const { data: auth } = (0, import_swr5.default)(
1609
- "authenticate",
2978
+ (0, import_date_fns10.isBefore)(state.auth.expires_at, /* @__PURE__ */ new Date()) && "authenticate",
1610
2979
  Layer.authenticate({
1611
2980
  appId,
1612
2981
  appSecret,
@@ -1616,30 +2985,199 @@ var LayerProvider = ({
1616
2985
  }),
1617
2986
  defaultSWRConfig
1618
2987
  );
1619
- (0, import_react22.useEffect)(() => {
1620
- if (!!auth?.access_token) {
1621
- dispatch({ type: "LayerContext.setAuth" /* setAuth */, payload: { auth } });
2988
+ (0, import_react39.useEffect)(() => {
2989
+ if (auth?.access_token) {
2990
+ dispatch({
2991
+ type: "LayerContext.setAuth" /* setAuth */,
2992
+ payload: {
2993
+ auth: {
2994
+ ...auth,
2995
+ expires_at: (0, import_date_fns10.add)(/* @__PURE__ */ new Date(), { seconds: auth.expires_in })
2996
+ }
2997
+ }
2998
+ });
1622
2999
  }
1623
3000
  }, [auth?.access_token]);
1624
3001
  const { data: categories } = (0, import_swr5.default)(
1625
3002
  businessId && auth?.access_token && `categories-${businessId}`,
1626
- Layer.getCategories(auth?.access_token, { params: { businessId } }),
3003
+ Layer.getCategories(apiUrl, auth?.access_token, { params: { businessId } }),
1627
3004
  defaultSWRConfig
1628
3005
  );
1629
- (0, import_react22.useEffect)(() => {
1630
- if (!!categories?.data?.categories?.length) {
3006
+ (0, import_react39.useEffect)(() => {
3007
+ if (categories?.data?.categories?.length) {
1631
3008
  dispatch({
1632
3009
  type: "LayerContext.setCategories" /* setCategories */,
1633
3010
  payload: { categories: categories.data.categories || [] }
1634
3011
  });
1635
3012
  }
1636
3013
  }, [categories?.data?.categories?.length]);
1637
- return /* @__PURE__ */ import_react22.default.createElement(import_swr5.SWRConfig, { value: defaultSWRConfig }, /* @__PURE__ */ import_react22.default.createElement(LayerContext.Provider, { value: state }, children));
3014
+ const setTheme = (theme2) => dispatch({
3015
+ type: "LayerContext.setTheme" /* setTheme */,
3016
+ payload: { theme: theme2 }
3017
+ });
3018
+ return /* @__PURE__ */ import_react39.default.createElement(import_swr5.SWRConfig, { value: defaultSWRConfig }, /* @__PURE__ */ import_react39.default.createElement(LayerContext.Provider, { value: { ...state, setTheme } }, children));
3019
+ };
3020
+
3021
+ // src/components/ChartOfAccounts/ChartOfAccounts.tsx
3022
+ var import_react42 = __toESM(require("react"));
3023
+
3024
+ // src/hooks/useChartOfAccounts/useChartOfAccounts.tsx
3025
+ var import_swr6 = __toESM(require("swr"));
3026
+ var useChartOfAccounts = () => {
3027
+ const { auth, businessId, apiUrl } = useLayerContext();
3028
+ const { data, isLoading, error, mutate } = (0, import_swr6.default)(
3029
+ businessId && auth?.access_token && `chart-of-accounts-${businessId}`,
3030
+ Layer.getChartOfAccounts(apiUrl, auth?.access_token, {
3031
+ params: { businessId }
3032
+ })
3033
+ );
3034
+ const create = (newAccount) => Layer.createAccount(apiUrl, auth?.access_token, {
3035
+ params: { businessId },
3036
+ body: newAccount
3037
+ }).then(({ data: data2 }) => (mutate(), data2));
3038
+ return { data: data?.data, isLoading, error, create };
3039
+ };
3040
+
3041
+ // src/components/ChartOfAccountsNewForm/ChartOfAccountsNewForm.tsx
3042
+ var import_react40 = __toESM(require("react"));
3043
+ var import_react_select2 = __toESM(require("react-select"));
3044
+ var flattenAccounts = (accounts) => accounts.flatMap((a) => [a, flattenAccounts(a.subAccounts || [])]).flat().filter((id) => id);
3045
+ var ChartOfAccountsNewForm = () => {
3046
+ const { data, create: createAccount2 } = useChartOfAccounts();
3047
+ const accountOptions = (0, import_react40.useMemo)(
3048
+ () => flattenAccounts(data?.accounts || []).sort(
3049
+ (a, b) => a?.name && b?.name ? a.name.localeCompare(b.name) : 0
3050
+ ),
3051
+ [data?.accounts?.length]
3052
+ );
3053
+ const [name, setName] = (0, import_react40.useState)("");
3054
+ const [description, setDescription] = (0, import_react40.useState)("");
3055
+ const [normality, setNormality] = (0, import_react40.useState)("DEBIT" /* DEBIT */);
3056
+ const [parentAccount, setParentAccount] = (0, import_react40.useState)(
3057
+ data?.accounts[0]
3058
+ );
3059
+ const save = () => {
3060
+ createAccount2({
3061
+ name,
3062
+ normality,
3063
+ parent_id: {
3064
+ type: "AccountId",
3065
+ id: parentAccount?.id || ""
3066
+ },
3067
+ description
3068
+ });
3069
+ };
3070
+ return /* @__PURE__ */ import_react40.default.createElement("div", { className: "Layer__chart-of-accounts-new-form" }, /* @__PURE__ */ import_react40.default.createElement("div", { className: "Layer__chart-of-accounts-new-form__field" }, /* @__PURE__ */ import_react40.default.createElement("span", null, "Name"), /* @__PURE__ */ import_react40.default.createElement(
3071
+ "input",
3072
+ {
3073
+ name: "name",
3074
+ value: name,
3075
+ onChange: (event) => setName(event.target.value)
3076
+ }
3077
+ )), /* @__PURE__ */ import_react40.default.createElement("div", { className: "Layer__chart-of-accounts-new-form__field" }, /* @__PURE__ */ import_react40.default.createElement("span", null, "Description"), /* @__PURE__ */ import_react40.default.createElement(
3078
+ "input",
3079
+ {
3080
+ name: "description",
3081
+ value: description,
3082
+ onChange: (event) => setDescription(event.target.value)
3083
+ }
3084
+ )), /* @__PURE__ */ import_react40.default.createElement("div", { className: "Layer__chart-of-accounts-new-form__field" }, /* @__PURE__ */ import_react40.default.createElement("span", null, "Normality"), /* @__PURE__ */ import_react40.default.createElement(
3085
+ import_react_select2.default,
3086
+ {
3087
+ isSearchable: false,
3088
+ onChange: (value) => value && setNormality(value.value),
3089
+ options: [
3090
+ { label: "Credit", value: "CREDIT" /* CREDIT */ },
3091
+ { label: "Debit", value: "DEBIT" /* DEBIT */ }
3092
+ ]
3093
+ }
3094
+ )), /* @__PURE__ */ import_react40.default.createElement("div", { className: "Layer__chart-of-accounts-new-form__field" }, /* @__PURE__ */ import_react40.default.createElement("span", null, "Parent Account"), /* @__PURE__ */ import_react40.default.createElement(
3095
+ import_react_select2.default,
3096
+ {
3097
+ isSearchable: true,
3098
+ value: parentAccount,
3099
+ onChange: (value) => value && setParentAccount(value),
3100
+ getOptionLabel: (a) => a.name,
3101
+ getOptionValue: (a) => a.id,
3102
+ options: accountOptions
3103
+ }
3104
+ )), /* @__PURE__ */ import_react40.default.createElement("div", { className: "Layer__chart-of-accounts-new-form__field Layer__chart-of-accounts-new-form__field--actions" }, /* @__PURE__ */ import_react40.default.createElement("button", { onClick: save }, "Save")));
3105
+ };
3106
+
3107
+ // src/components/ChartOfAccountsRow/ChartOfAccountsRow.tsx
3108
+ var import_react41 = __toESM(require("react"));
3109
+ var ChartOfAccountsRow = ({ account, depth = 0 }) => {
3110
+ const classNames12 = [
3111
+ "Layer__chart-of-accounts-row__table-cell",
3112
+ depth > 0 && `Layer__chart-of-accounts-row__table-cell--depth-${depth}`
3113
+ ];
3114
+ const className = classNames12.filter((id) => id).join(" ");
3115
+ const amountClassName = account.balance < 0 ? "Layer__chart-of-accounts-row__table-cell--amount-negative" : "Layer__chart-of-accounts-row__table-cell--amount-positive";
3116
+ return /* @__PURE__ */ import_react41.default.createElement(import_react41.default.Fragment, null, /* @__PURE__ */ import_react41.default.createElement(
3117
+ "div",
3118
+ {
3119
+ className: `${className} Layer__chart-of-accounts-row__table-cell--name`
3120
+ },
3121
+ account.name
3122
+ ), /* @__PURE__ */ import_react41.default.createElement(
3123
+ "div",
3124
+ {
3125
+ className: `${className} Layer__chart-of-accounts-row__table-cell--type`
3126
+ },
3127
+ "Assets"
3128
+ ), /* @__PURE__ */ import_react41.default.createElement(
3129
+ "div",
3130
+ {
3131
+ className: `${className} Layer__chart-of-accounts-row__table-cell--subtype`
3132
+ },
3133
+ "Cash"
3134
+ ), /* @__PURE__ */ import_react41.default.createElement(
3135
+ "div",
3136
+ {
3137
+ className: `${className} Layer__chart-of-accounts-row__table-cell--balance ${amountClassName}`
3138
+ },
3139
+ centsToDollars(Math.abs(account.balance || 0))
3140
+ ), /* @__PURE__ */ import_react41.default.createElement(
3141
+ "div",
3142
+ {
3143
+ className: `${className} Layer__chart-of-accounts-row__table-cell--actions`
3144
+ },
3145
+ /* @__PURE__ */ import_react41.default.createElement("button", { className: "Layer__chart-of-accounts-row__view-entries-button" }, "View Entries")
3146
+ ), (account.subAccounts || []).map((subAccount) => /* @__PURE__ */ import_react41.default.createElement(
3147
+ ChartOfAccountsRow,
3148
+ {
3149
+ key: subAccount.id,
3150
+ account: subAccount,
3151
+ depth: depth + 1
3152
+ }
3153
+ )));
3154
+ };
3155
+
3156
+ // src/components/ChartOfAccounts/ChartOfAccounts.tsx
3157
+ var ChartOfAccounts = () => {
3158
+ const { data, isLoading } = useChartOfAccounts();
3159
+ const [showingForm, setShowingForm] = (0, import_react42.useState)(false);
3160
+ return /* @__PURE__ */ import_react42.default.createElement("div", { className: "Layer__component Layer__chart-of-accounts" }, !data || isLoading ? "Loading." : /* @__PURE__ */ import_react42.default.createElement(import_react42.default.Fragment, null, /* @__PURE__ */ import_react42.default.createElement("div", { className: "Layer__chart-of-accounts__header" }, /* @__PURE__ */ import_react42.default.createElement("h2", { className: "Layer__chart-of-accounts__title" }, "Chart of Accounts"), /* @__PURE__ */ import_react42.default.createElement("div", { className: "Layer__chart-of-accounts__actions" }, /* @__PURE__ */ import_react42.default.createElement("button", { className: "Layer__chart-of-accounts__download-button" }, /* @__PURE__ */ import_react42.default.createElement(DownloadCloud_default, null), "Download"), /* @__PURE__ */ import_react42.default.createElement(
3161
+ "button",
3162
+ {
3163
+ className: "Layer__chart-of-accounts__edit-accounts-button",
3164
+ onClick: () => setShowingForm(!showingForm)
3165
+ },
3166
+ "Edit Accounts"
3167
+ ))), showingForm && /* @__PURE__ */ import_react42.default.createElement(ChartOfAccountsNewForm, null), /* @__PURE__ */ import_react42.default.createElement("div", { className: "Layer__chart-of-accounts__table" }, /* @__PURE__ */ import_react42.default.createElement("div", { className: "Layer__chart-of-accounts__table-cell Layer__chart-of-accounts__table-cell--header" }, "Name"), /* @__PURE__ */ import_react42.default.createElement("div", { className: "Layer__chart-of-accounts__table-cell Layer__chart-of-accounts__table-cell--header" }, "Type"), /* @__PURE__ */ import_react42.default.createElement("div", { className: "Layer__chart-of-accounts__table-cell Layer__chart-of-accounts__table-cell--header" }, "Sub-Type"), /* @__PURE__ */ import_react42.default.createElement("div", { className: "Layer__chart-of-accounts__table-cell Layer__chart-of-accounts__table-cell--header Layer__chart-of-accounts__table-cell--header-balance" }, "Balance"), /* @__PURE__ */ import_react42.default.createElement("div", { className: "Layer__chart-of-accounts__table-cell Layer__chart-of-accounts__table-cell--header" }), data.accounts.map((account) => /* @__PURE__ */ import_react42.default.createElement(
3168
+ ChartOfAccountsRow,
3169
+ {
3170
+ key: account.id,
3171
+ account,
3172
+ depth: 0
3173
+ }
3174
+ )))));
1638
3175
  };
1639
3176
  // Annotate the CommonJS export names for ESM import in node:
1640
3177
  0 && (module.exports = {
1641
3178
  BalanceSheet,
1642
3179
  BankTransactions,
3180
+ ChartOfAccounts,
1643
3181
  Hello,
1644
3182
  LayerProvider,
1645
3183
  ProfitAndLoss