@aprovan/bobbin 0.1.0-dev.6bd527d

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 (45) hide show
  1. package/.turbo/turbo-build.log +16 -0
  2. package/LICENSE +373 -0
  3. package/dist/index.d.ts +402 -0
  4. package/dist/index.js +3704 -0
  5. package/package.json +30 -0
  6. package/src/Bobbin.tsx +89 -0
  7. package/src/components/EditPanel/EditPanel.tsx +376 -0
  8. package/src/components/EditPanel/controls/ColorPicker.tsx +138 -0
  9. package/src/components/EditPanel/controls/QuickSelectDropdown.tsx +142 -0
  10. package/src/components/EditPanel/controls/SliderInput.tsx +94 -0
  11. package/src/components/EditPanel/controls/SpacingControl.tsx +285 -0
  12. package/src/components/EditPanel/controls/ToggleGroup.tsx +37 -0
  13. package/src/components/EditPanel/controls/TokenDropdown.tsx +33 -0
  14. package/src/components/EditPanel/sections/AnnotationSection.tsx +136 -0
  15. package/src/components/EditPanel/sections/BackgroundSection.tsx +79 -0
  16. package/src/components/EditPanel/sections/EffectsSection.tsx +85 -0
  17. package/src/components/EditPanel/sections/LayoutSection.tsx +224 -0
  18. package/src/components/EditPanel/sections/SectionWrapper.tsx +57 -0
  19. package/src/components/EditPanel/sections/SizeSection.tsx +166 -0
  20. package/src/components/EditPanel/sections/SpacingSection.tsx +69 -0
  21. package/src/components/EditPanel/sections/TypographySection.tsx +148 -0
  22. package/src/components/Inspector/Inspector.tsx +221 -0
  23. package/src/components/Overlay/ControlHandles.tsx +572 -0
  24. package/src/components/Overlay/MarginPaddingOverlay.tsx +229 -0
  25. package/src/components/Overlay/SelectionOverlay.tsx +73 -0
  26. package/src/components/Pill/Pill.tsx +155 -0
  27. package/src/components/ThemeToggle/ThemeToggle.tsx +72 -0
  28. package/src/core/changeSerializer.ts +139 -0
  29. package/src/core/useBobbin.ts +399 -0
  30. package/src/core/useChangeTracker.ts +186 -0
  31. package/src/core/useClipboard.ts +21 -0
  32. package/src/core/useElementSelection.ts +146 -0
  33. package/src/index.ts +46 -0
  34. package/src/tokens/borders.ts +19 -0
  35. package/src/tokens/colors.ts +150 -0
  36. package/src/tokens/index.ts +37 -0
  37. package/src/tokens/shadows.ts +10 -0
  38. package/src/tokens/spacing.ts +37 -0
  39. package/src/tokens/typography.ts +51 -0
  40. package/src/types.ts +157 -0
  41. package/src/utils/animation.ts +40 -0
  42. package/src/utils/dom.ts +36 -0
  43. package/src/utils/selectors.ts +76 -0
  44. package/tsconfig.json +10 -0
  45. package/tsup.config.ts +10 -0
@@ -0,0 +1,36 @@
1
+ export function applyStyleToElement(
2
+ el: HTMLElement,
3
+ property: string,
4
+ value: string,
5
+ ): void {
6
+ el.style.setProperty(property, value);
7
+ }
8
+
9
+ export function enableContentEditable(el: HTMLElement, enabled: boolean): void {
10
+ if (enabled) {
11
+ el.contentEditable = 'true';
12
+ // Recursively enable for text nodes
13
+ const textElements = el.querySelectorAll(
14
+ 'p, span, h1, h2, h3, h4, h5, h6, a, li, td, th, label, div',
15
+ );
16
+ textElements.forEach((child) => {
17
+ if (child instanceof HTMLElement && child.childNodes.length > 0) {
18
+ // Only make editable if it has direct text content
19
+ for (const node of child.childNodes) {
20
+ if (node.nodeType === Node.TEXT_NODE && node.textContent?.trim()) {
21
+ child.contentEditable = 'true';
22
+ break;
23
+ }
24
+ }
25
+ }
26
+ });
27
+ } else {
28
+ el.contentEditable = 'false';
29
+ const textElements = el.querySelectorAll('[contenteditable="true"]');
30
+ textElements.forEach((child) => {
31
+ if (child instanceof HTMLElement) {
32
+ child.contentEditable = 'false';
33
+ }
34
+ });
35
+ }
36
+ }
@@ -0,0 +1,76 @@
1
+ export function generateId(): string {
2
+ return Math.random().toString(36).substring(2, 15);
3
+ }
4
+
5
+ export function getElementPath(el: HTMLElement): string {
6
+ const path: string[] = [];
7
+ let current: HTMLElement | null = el;
8
+
9
+ while (current && current !== document.body) {
10
+ let selector = current.tagName.toLowerCase();
11
+
12
+ if (current.id) {
13
+ selector = `#${current.id}`;
14
+ path.unshift(selector);
15
+ break;
16
+ }
17
+
18
+ // Add nth-child for uniqueness
19
+ const parent = current.parentElement;
20
+ if (parent) {
21
+ const siblings = Array.from(parent.children).filter(
22
+ (c) => c.tagName === current!.tagName,
23
+ );
24
+ if (siblings.length > 1) {
25
+ const index = siblings.indexOf(current) + 1;
26
+ selector += `:nth-of-type(${index})`;
27
+ }
28
+ }
29
+
30
+ path.unshift(selector);
31
+ current = current.parentElement;
32
+ }
33
+
34
+ return path.join(' > ');
35
+ }
36
+
37
+ export function getElementXPath(el: HTMLElement): string {
38
+ const parts: string[] = [];
39
+ let current: HTMLElement | null = el;
40
+
41
+ while (
42
+ current &&
43
+ current !== document.body &&
44
+ current !== document.documentElement
45
+ ) {
46
+ let part = current.tagName.toLowerCase();
47
+
48
+ // If element has an id, use it as anchor
49
+ if (current.id) {
50
+ parts.unshift(`//*[@id="${current.id}"]`);
51
+ break;
52
+ }
53
+
54
+ // Calculate position among siblings of same tag
55
+ const parent = current.parentElement;
56
+ if (parent) {
57
+ const siblings = Array.from(parent.children).filter(
58
+ (c) => c.tagName === current!.tagName,
59
+ );
60
+ if (siblings.length > 1) {
61
+ const index = siblings.indexOf(current) + 1;
62
+ part += `[${index}]`;
63
+ }
64
+ }
65
+
66
+ parts.unshift(part);
67
+ current = current.parentElement;
68
+ }
69
+
70
+ // If we didn't find an id anchor, start from root
71
+ if (!parts[0]?.startsWith('//*[@id')) {
72
+ parts.unshift('');
73
+ }
74
+
75
+ return parts.join('/') || '//' + el.tagName.toLowerCase();
76
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "outDir": "./dist",
5
+ "rootDir": "./src",
6
+ "jsx": "react-jsx"
7
+ },
8
+ "include": ["src/**/*"],
9
+ "exclude": ["node_modules", "dist"]
10
+ }
package/tsup.config.ts ADDED
@@ -0,0 +1,10 @@
1
+ import { defineConfig } from 'tsup';
2
+
3
+ export default defineConfig({
4
+ entry: ['src/index.ts'],
5
+ format: ['esm'],
6
+ dts: true,
7
+ clean: true,
8
+ external: ['react', 'react-dom'],
9
+ treeshake: true,
10
+ });