socialcalc-ai 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +268 -0
  2. package/components/CellEditModal/CellEditModal.css +584 -0
  3. package/components/CellEditModal/CellEditModal.tsx +817 -0
  4. package/components/DemoVideosModal/DemoVideosModal.css +307 -0
  5. package/components/DemoVideosModal/DemoVideosModal.tsx +289 -0
  6. package/components/EditableCellsModal/EditableCellsModal.css +346 -0
  7. package/components/EditableCellsModal/EditableCellsModal.tsx +555 -0
  8. package/components/HorizontalScrollBar.css +127 -0
  9. package/components/HorizontalScrollBar.tsx +140 -0
  10. package/components/RowActionPopover/RowActionPopover.css +95 -0
  11. package/components/RowActionPopover/RowActionPopover.tsx +82 -0
  12. package/core/constants.js +1039 -0
  13. package/core/core.js +7172 -0
  14. package/core/format-number.js +7034 -0
  15. package/core/formula.js +1675 -0
  16. package/core/index.js +28 -0
  17. package/core/spreadsheet-control.js +7646 -0
  18. package/core/table-editor.js +8156 -0
  19. package/index.d.ts +68 -0
  20. package/index.js +43 -0
  21. package/modules/device.js +22 -0
  22. package/modules/editable-cells.js +230 -0
  23. package/modules/exporters.js +22 -0
  24. package/modules/formatting.js +258 -0
  25. package/modules/grid-lines.js +127 -0
  26. package/modules/history.js +26 -0
  27. package/modules/horizontal-scroll.js +335 -0
  28. package/modules/init.js +94 -0
  29. package/modules/invoice.js +558 -0
  30. package/modules/listeners.js +531 -0
  31. package/modules/logos.js +191 -0
  32. package/modules/plugin-manager.js +208 -0
  33. package/modules/prompts.js +170 -0
  34. package/modules/row-col-headers.js +514 -0
  35. package/modules/sheets.js +151 -0
  36. package/modules/touch-scroll.js +474 -0
  37. package/modules/utils.js +317 -0
  38. package/modules/weight.js +287 -0
  39. package/package.json +67 -0
  40. package/utils/imageCompressor.ts +118 -0
  41. package/utils/scriptLoader.ts +39 -0
@@ -0,0 +1,140 @@
1
+ import React, { useEffect, useState, useCallback } from "react";
2
+ import {
3
+ getHorizontalScrollInfo,
4
+ scrollToColumn,
5
+ scrollHorizontalBy,
6
+ subscribeHorizontalScroll
7
+ } from "../modules/horizontal-scroll.js";
8
+ import "./HorizontalScrollBar.css";
9
+
10
+ export interface HorizontalScrollBarProps {
11
+ /** Optional custom step size for arrow button clicks (default: 1) */
12
+ step?: number;
13
+ /** Optional CSS class name */
14
+ className?: string;
15
+ /** Optional callback when column changes */
16
+ onColumnChange?: (colInfo: { firstCol: number; colName: string; totalCols: number }) => void;
17
+ }
18
+
19
+ export const HorizontalScrollBar: React.FC<HorizontalScrollBarProps> = ({
20
+ step = 1,
21
+ className = "",
22
+ onColumnChange
23
+ }) => {
24
+ const [scrollInfo, setScrollInfo] = useState(() => getHorizontalScrollInfo());
25
+
26
+ // Subscribe to external scroll events (e.g. from gestures or programmatic scrolls)
27
+ useEffect(() => {
28
+ // Initial sync
29
+ setScrollInfo(getHorizontalScrollInfo());
30
+
31
+ const unsubscribe = subscribeHorizontalScroll((info) => {
32
+ setScrollInfo(info);
33
+ if (onColumnChange) {
34
+ onColumnChange({
35
+ firstCol: info.currentFirstCol,
36
+ colName: info.currentColName,
37
+ totalCols: info.totalCols
38
+ });
39
+ }
40
+ });
41
+
42
+ // Also listen to custom window events for extra compatibility
43
+ const handleCustomScroll = (e: any) => {
44
+ if (e.detail) {
45
+ setScrollInfo(e.detail);
46
+ }
47
+ };
48
+ window.addEventListener("socialcalc:horizontal-scroll", handleCustomScroll);
49
+
50
+ // Periodic check to keep in sync if canvas/DOM scrolls without direct event
51
+ const timer = setInterval(() => {
52
+ const current = getHorizontalScrollInfo();
53
+ setScrollInfo((prev) => {
54
+ if (
55
+ prev.currentFirstCol !== current.currentFirstCol ||
56
+ prev.totalCols !== current.totalCols
57
+ ) {
58
+ return current;
59
+ }
60
+ return prev;
61
+ });
62
+ }, 400);
63
+
64
+ return () => {
65
+ unsubscribe();
66
+ window.removeEventListener("socialcalc:horizontal-scroll", handleCustomScroll);
67
+ clearInterval(timer);
68
+ };
69
+ }, [onColumnChange]);
70
+
71
+ const handlePrev = useCallback(() => {
72
+ scrollHorizontalBy(-step);
73
+ }, [step]);
74
+
75
+ const handleNext = useCallback(() => {
76
+ scrollHorizontalBy(step);
77
+ }, [step]);
78
+
79
+ const handleSliderChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
80
+ const val = parseInt(e.target.value, 10);
81
+ scrollToColumn(val);
82
+ }, []);
83
+
84
+ const isAtStart = scrollInfo.currentFirstCol <= 1;
85
+ const isAtEnd = scrollInfo.currentFirstCol >= scrollInfo.totalCols;
86
+
87
+ return (
88
+ <div className={`sc-hscroll-container ${className}`}>
89
+ {/* Left Arrow Button */}
90
+ <button
91
+ type="button"
92
+ className="sc-hscroll-btn"
93
+ onClick={handlePrev}
94
+ disabled={isAtStart}
95
+ title={`Scroll Left (${step} Column)`}
96
+ aria-label="Scroll Left"
97
+ >
98
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
99
+ <polyline points="15 18 9 12 15 6" />
100
+ </svg>
101
+ </button>
102
+
103
+ {/* Slider and Pill */}
104
+ <div className="sc-hscroll-track-wrapper">
105
+ <input
106
+ type="range"
107
+ className="sc-hscroll-slider"
108
+ min={1}
109
+ max={scrollInfo.totalCols}
110
+ value={scrollInfo.currentFirstCol}
111
+ onChange={handleSliderChange}
112
+ aria-label="Horizontal Column Slider"
113
+ />
114
+
115
+ <div className="sc-hscroll-indicator">
116
+ <span>Col {scrollInfo.currentColName}</span>
117
+ <span style={{ opacity: 0.65, fontSize: "10px" }}>
118
+ ({scrollInfo.currentFirstCol}/{scrollInfo.totalCols})
119
+ </span>
120
+ </div>
121
+ </div>
122
+
123
+ {/* Right Arrow Button */}
124
+ <button
125
+ type="button"
126
+ className="sc-hscroll-btn"
127
+ onClick={handleNext}
128
+ disabled={isAtEnd}
129
+ title={`Scroll Right (${step} Column)`}
130
+ aria-label="Scroll Right"
131
+ >
132
+ <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
133
+ <polyline points="9 18 15 12 9 6" />
134
+ </svg>
135
+ </button>
136
+ </div>
137
+ );
138
+ };
139
+
140
+ export default HorizontalScrollBar;
@@ -0,0 +1,95 @@
1
+ /* Row Action Popover Styles — Clean, Professional */
2
+
3
+ .sc-row-popover-backdrop {
4
+ position: fixed;
5
+ top: 0;
6
+ left: 0;
7
+ right: 0;
8
+ bottom: 0;
9
+ z-index: 9999;
10
+ background: transparent;
11
+ }
12
+
13
+ .sc-row-popover-menu {
14
+ position: fixed;
15
+ background: #ffffff;
16
+ border-radius: 8px;
17
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12), 0 0 0 1px rgba(0, 0, 0, 0.06);
18
+ padding: 4px;
19
+ min-width: 160px;
20
+ z-index: 10000;
21
+ display: flex;
22
+ flex-direction: column;
23
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
24
+ animation: scPopoverFade 0.12s ease-out;
25
+ }
26
+
27
+ @keyframes scPopoverFade {
28
+ from { opacity: 0; transform: translateY(-2px); }
29
+ to { opacity: 1; transform: translateY(0); }
30
+ }
31
+
32
+ .sc-row-popover-header {
33
+ padding: 6px 10px 4px 10px;
34
+ }
35
+
36
+ .sc-row-popover-title {
37
+ font-size: 11px;
38
+ font-weight: 600;
39
+ color: #94a3b8;
40
+ text-transform: uppercase;
41
+ letter-spacing: 0.3px;
42
+ }
43
+
44
+ .sc-row-popover-divider {
45
+ height: 1px;
46
+ background: #e2e8f0;
47
+ margin: 2px 6px;
48
+ }
49
+
50
+ .sc-row-popover-item {
51
+ display: flex;
52
+ align-items: center;
53
+ gap: 8px;
54
+ padding: 7px 10px;
55
+ border-radius: 5px;
56
+ border: none;
57
+ background: transparent;
58
+ color: #334155;
59
+ font-size: 13px;
60
+ font-weight: 500;
61
+ cursor: pointer;
62
+ width: 100%;
63
+ text-align: left;
64
+ transition: background 0.1s ease;
65
+ }
66
+
67
+ .sc-row-popover-item:hover {
68
+ background: #f1f5f9;
69
+ }
70
+
71
+ .sc-row-popover-item:active {
72
+ background: #e2e8f0;
73
+ }
74
+
75
+ .sc-row-popover-item.danger {
76
+ color: #dc2626;
77
+ }
78
+
79
+ .sc-row-popover-item.danger:hover {
80
+ background: #fef2f2;
81
+ }
82
+
83
+ .sc-row-popover-icon {
84
+ font-size: 14px;
85
+ font-weight: 700;
86
+ width: 18px;
87
+ display: flex;
88
+ align-items: center;
89
+ justify-content: center;
90
+ color: #94a3b8;
91
+ }
92
+
93
+ .sc-row-popover-item.danger .sc-row-popover-icon {
94
+ color: #dc2626;
95
+ }
@@ -0,0 +1,82 @@
1
+ import React from "react";
2
+ import "./RowActionPopover.css";
3
+
4
+ export interface RowActionPopoverProps {
5
+ isOpen: boolean;
6
+ rowNum: number | null;
7
+ position: { x: number; y: number } | null;
8
+ onClose: () => void;
9
+ onInsertAbove: (rowNum: number) => void;
10
+ onInsertBelow: (rowNum: number) => void;
11
+ onDeleteRow: (rowNum: number) => void;
12
+ }
13
+
14
+ export const RowActionPopover: React.FC<RowActionPopoverProps> = ({
15
+ isOpen,
16
+ rowNum,
17
+ position,
18
+ onClose,
19
+ onInsertAbove,
20
+ onInsertBelow,
21
+ onDeleteRow,
22
+ }) => {
23
+ if (!isOpen || rowNum === null || !position) return null;
24
+
25
+ // Ensure popover stays within viewport bounds
26
+ const left = Math.min(window.innerWidth - 200, Math.max(10, position.x + 8));
27
+ const top = Math.min(window.innerHeight - 180, Math.max(10, position.y - 10));
28
+
29
+ return (
30
+ <>
31
+ <div className="sc-row-popover-backdrop" onClick={onClose} />
32
+ <div
33
+ className="sc-row-popover-menu"
34
+ style={{ left: `${left}px`, top: `${top}px` }}
35
+ >
36
+ <div className="sc-row-popover-header">
37
+ <span className="sc-row-popover-title">Row {rowNum}</span>
38
+ </div>
39
+
40
+ <button
41
+ type="button"
42
+ className="sc-row-popover-item"
43
+ onClick={() => {
44
+ onInsertAbove(rowNum);
45
+ onClose();
46
+ }}
47
+ >
48
+ <span className="sc-row-popover-icon">+</span>
49
+ <span>Insert above</span>
50
+ </button>
51
+
52
+ <button
53
+ type="button"
54
+ className="sc-row-popover-item"
55
+ onClick={() => {
56
+ onInsertBelow(rowNum);
57
+ onClose();
58
+ }}
59
+ >
60
+ <span className="sc-row-popover-icon">+</span>
61
+ <span>Insert below</span>
62
+ </button>
63
+
64
+ <div className="sc-row-popover-divider" />
65
+
66
+ <button
67
+ type="button"
68
+ className="sc-row-popover-item danger"
69
+ onClick={() => {
70
+ onDeleteRow(rowNum);
71
+ onClose();
72
+ }}
73
+ >
74
+ <span className="sc-row-popover-icon">&minus;</span>
75
+ <span>Delete row</span>
76
+ </button>
77
+ </div>
78
+ </>
79
+ );
80
+ };
81
+
82
+ export default RowActionPopover;