@wire-dsl/web 0.0.7 → 0.1.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 (127) hide show
  1. package/.turbo/turbo-build.log +103 -7
  2. package/CHANGELOG.md +30 -3
  3. package/dist/assets/abap-DLDM7-KI.js +1 -0
  4. package/dist/assets/apex-DNDY2TF8.js +1 -0
  5. package/dist/assets/azcli-Y6nb8tq_.js +1 -0
  6. package/dist/assets/bat-BwHxbl9M.js +1 -0
  7. package/dist/assets/bicep-CFznDFnq.js +2 -0
  8. package/dist/assets/cameligo-Bf6VGUru.js +1 -0
  9. package/dist/assets/clojure-Dnu-v4kV.js +1 -0
  10. package/dist/assets/codicon-ngg6Pgfi.ttf +0 -0
  11. package/dist/assets/coffee-Bd8akH9Z.js +1 -0
  12. package/dist/assets/cpp-BbWJElDN.js +1 -0
  13. package/dist/assets/csharp-Co3qMtFm.js +1 -0
  14. package/dist/assets/csp-D-4FJmMZ.js +1 -0
  15. package/dist/assets/css-DdJfP1eB.js +3 -0
  16. package/dist/assets/css.worker-DBVD8oXr.js +93 -0
  17. package/dist/assets/cssMode-BgkzAyoH.js +1 -0
  18. package/dist/assets/cypher-cTPe9QuQ.js +1 -0
  19. package/dist/assets/dart-BOtBlQCF.js +1 -0
  20. package/dist/assets/dockerfile-BG73LgW2.js +1 -0
  21. package/dist/assets/ecl-BEgZUVRK.js +1 -0
  22. package/dist/assets/elixir-BkW5O-1t.js +1 -0
  23. package/dist/assets/flow9-BeJ5waoc.js +1 -0
  24. package/dist/assets/freemarker2-D05KrEgD.js +3 -0
  25. package/dist/assets/fsharp-PahG7c26.js +1 -0
  26. package/dist/assets/go-acbASCJo.js +1 -0
  27. package/dist/assets/graphql-BxJiqAUM.js +1 -0
  28. package/dist/assets/handlebars-CmNF6dIr.js +1 -0
  29. package/dist/assets/hcl-DtV1sZF8.js +1 -0
  30. package/dist/assets/html-DdFfMtqo.js +1 -0
  31. package/dist/assets/html.worker-CwpTb9lJ.js +470 -0
  32. package/dist/assets/htmlMode-BzENSv3x.js +1 -0
  33. package/dist/assets/index-C6yQ9VSx.js +1595 -0
  34. package/dist/assets/index-CmAJnnOw.css +1 -0
  35. package/dist/assets/ini-Kd9XrMLS.js +1 -0
  36. package/dist/assets/java-CXBNlu9o.js +1 -0
  37. package/dist/assets/javascript-BDq34vkg.js +1 -0
  38. package/dist/assets/json.worker-BoL8UZqY.js +58 -0
  39. package/dist/assets/jsonMode-xsVJWt4Q.js +7 -0
  40. package/dist/assets/julia-cl7-CwDS.js +1 -0
  41. package/dist/assets/kotlin-s7OhZKlX.js +1 -0
  42. package/dist/assets/less-9HpZscsL.js +2 -0
  43. package/dist/assets/lexon-OrD6JF1K.js +1 -0
  44. package/dist/assets/liquid-BKLduW-j.js +1 -0
  45. package/dist/assets/lspLanguageFeatures-DENz5XIL.js +4 -0
  46. package/dist/assets/lua-Cyyb5UIc.js +1 -0
  47. package/dist/assets/m3-B8OfTtLu.js +1 -0
  48. package/dist/assets/markdown-BFxVWTOG.js +1 -0
  49. package/dist/assets/mdx-Cpg3g8iv.js +1 -0
  50. package/dist/assets/mips-CiqrrVzr.js +1 -0
  51. package/dist/assets/msdax-DmeGPVcC.js +1 -0
  52. package/dist/assets/mysql-C_tMU-Nz.js +1 -0
  53. package/dist/assets/objective-c-BDtDVThU.js +1 -0
  54. package/dist/assets/pascal-vHIfCaH5.js +1 -0
  55. package/dist/assets/pascaligo-DtZ0uQbO.js +1 -0
  56. package/dist/assets/perl-Ub6l9XKa.js +1 -0
  57. package/dist/assets/pgsql-BlNEE0v7.js +1 -0
  58. package/dist/assets/php-BBUBE1dy.js +1 -0
  59. package/dist/assets/pla-DSh2-awV.js +1 -0
  60. package/dist/assets/postiats-CocnycG-.js +1 -0
  61. package/dist/assets/powerquery-tScXyioY.js +1 -0
  62. package/dist/assets/powershell-COWaemsV.js +1 -0
  63. package/dist/assets/protobuf-Brw8urJB.js +2 -0
  64. package/dist/assets/pug-8SOpv6rk.js +1 -0
  65. package/dist/assets/python-Ca2JvAvf.js +1 -0
  66. package/dist/assets/qsharp-Bw9ernYp.js +1 -0
  67. package/dist/assets/r-j7ic8hl3.js +1 -0
  68. package/dist/assets/razor-B_xld0Yq.js +1 -0
  69. package/dist/assets/redis-Bu5POkcn.js +1 -0
  70. package/dist/assets/redshift-Bs9aos_-.js +1 -0
  71. package/dist/assets/restructuredtext-CqXO7rUv.js +1 -0
  72. package/dist/assets/ruby-zBfavPgS.js +1 -0
  73. package/dist/assets/rust-BzKRNQWT.js +1 -0
  74. package/dist/assets/sb-BBc9UKZt.js +1 -0
  75. package/dist/assets/scala-D9hQfWCl.js +1 -0
  76. package/dist/assets/scheme-BPhDTwHR.js +1 -0
  77. package/dist/assets/scss-CBJaRo0y.js +3 -0
  78. package/dist/assets/shell-DiJ1NA_G.js +1 -0
  79. package/dist/assets/solidity-Db0IVjzk.js +1 -0
  80. package/dist/assets/sophia-CnS9iZB_.js +1 -0
  81. package/dist/assets/sparql-CJmd_6j2.js +1 -0
  82. package/dist/assets/sql-ClhHkBeG.js +1 -0
  83. package/dist/assets/st-CHwy0fLd.js +1 -0
  84. package/dist/assets/swift-CnmFD0ga.js +1 -0
  85. package/dist/assets/systemverilog-Bs9z6M-B.js +1 -0
  86. package/dist/assets/tcl-Dm6ycUr_.js +1 -0
  87. package/dist/assets/ts.worker-BH9nVgjN.js +67718 -0
  88. package/dist/assets/tsMode-BinQkqy9.js +11 -0
  89. package/dist/assets/twig-Csy3S7wG.js +1 -0
  90. package/dist/assets/typescript-DQO38ZbJ.js +1 -0
  91. package/dist/assets/typespec-Btyra-wh.js +1 -0
  92. package/dist/assets/vb-Db0cS2oM.js +1 -0
  93. package/dist/assets/wgsl-BTesnYfV.js +298 -0
  94. package/dist/assets/xml-DF1bgZg2.js +1 -0
  95. package/dist/assets/yaml-BiNWh9S_.js +1 -0
  96. package/dist/examples/admin-dashboard.wire +95 -0
  97. package/dist/examples/analytics-dashboard.wire +65 -0
  98. package/dist/examples/form-example.wire +50 -0
  99. package/dist/examples/simple-dashboard.wire +40 -0
  100. package/dist/examples/simple-multi-screen.wire +30 -0
  101. package/dist/index.html +2 -2
  102. package/package.json +5 -3
  103. package/postcss.config.mjs +3 -1
  104. package/public/examples/admin-dashboard.wire +95 -0
  105. package/public/examples/analytics-dashboard.wire +65 -0
  106. package/public/examples/form-example.wire +50 -0
  107. package/public/examples/simple-dashboard.wire +40 -0
  108. package/public/examples/simple-multi-screen.wire +30 -0
  109. package/src/App.tsx +3 -13
  110. package/src/components/MonacoEditorComponent.tsx +112 -0
  111. package/src/components/WireLiveEditor.tsx +729 -0
  112. package/src/components/WireLiveHeader.tsx +469 -0
  113. package/src/components/index.ts +5 -0
  114. package/src/hooks/useCanvasZoom.ts +137 -0
  115. package/src/hooks/useFileSystemAccess.ts +123 -0
  116. package/src/hooks/useWireParser.ts +222 -0
  117. package/src/index.css +1 -3
  118. package/src/main.tsx +7 -5
  119. package/src/monaco/wireLanguage.ts +370 -0
  120. package/src/store/editorStore.ts +196 -0
  121. package/src/store/index.ts +2 -0
  122. package/tailwind.config.js +2 -1
  123. package/vite.config.ts +17 -0
  124. package/dist/assets/index-CHiOjnNN.js +0 -9
  125. package/dist/assets/index-CUIy2zPc.css +0 -1
  126. package/src/App.js +0 -4
  127. package/src/main.js +0 -6
@@ -0,0 +1,50 @@
1
+ project "Form Example" {
2
+ theme {
3
+ density: "normal"
4
+ spacing: "md"
5
+ radius: "md"
6
+ stroke: "normal"
7
+ font: "base"
8
+ }
9
+
10
+ screen FormScreen {
11
+ layout stack(direction: vertical, gap: md, padding: lg) {
12
+ component Heading text: "User Registration"
13
+
14
+ component Text content: "Please fill in all required fields below"
15
+
16
+ layout stack(direction: vertical, gap: md, padding: md) {
17
+ component Input label: "Full Name" placeholder: "John Doe"
18
+
19
+ component Input label: "Email" placeholder: "john@example.com"
20
+
21
+ component Textarea label: "Bio" placeholder: "Tell us about yourself..." rows: 4
22
+
23
+ component Select label: "Country" items: "USA,Canada,Mexico,UK,Spain"
24
+
25
+ layout stack(direction: vertical, gap: sm, padding: md) {
26
+ component Heading text: "Preferences"
27
+
28
+ component Checkbox label: "Subscribe to newsletter"
29
+ component Checkbox label: "Enable notifications"
30
+ }
31
+
32
+ layout stack(direction: vertical, gap: sm, padding: md) {
33
+ component Heading text: "Account Type"
34
+
35
+ component Radio label: "Personal"
36
+ component Radio label: "Business"
37
+ }
38
+
39
+ layout stack(direction: vertical, gap: md) {
40
+ component Toggle label: "Terms & Conditions"
41
+ }
42
+ }
43
+
44
+ layout stack(direction: horizontal, gap: md) {
45
+ component Button text: "Cancel"
46
+ component Button text: "Submit" variant: primary
47
+ }
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,40 @@
1
+ project "Simple Dashboard" {
2
+ theme {
3
+ density: "comfortable"
4
+ spacing: "lg"
5
+ radius: "md"
6
+ stroke: "normal"
7
+ font: "base"
8
+ }
9
+
10
+ screen Dashboard {
11
+ layout stack(direction: vertical, gap: lg, padding: xl) {
12
+ component Topbar title: "Dashboard"
13
+
14
+ layout grid(columns: 12, gap: lg) {
15
+ cell span: 4 {
16
+ layout card(padding: md, gap: md) {
17
+ component Heading text: "Total Users"
18
+ component StatCard title: "Count" value: "2,543"
19
+ }
20
+ }
21
+ cell span: 4 {
22
+ layout card(padding: md, gap: md) {
23
+ component Heading text: "Active Sessions"
24
+ component StatCard title: "Active" value: "856"
25
+ }
26
+ }
27
+ cell span: 4 {
28
+ layout card(padding: md, gap: md) {
29
+ component Heading text: "Revenue"
30
+ component StatCard title: "Total" value: "$45.2K"
31
+ }
32
+ }
33
+ }
34
+
35
+ component ChartPlaceholder type: "bar" height: 300
36
+
37
+ component Table columns: "Date,Event,User" rows: 5
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,30 @@
1
+ project "Admin Dashboard Simple" {
2
+ theme {
3
+ density: "normal"
4
+ spacing: "md"
5
+ radius: "md"
6
+ stroke: "normal"
7
+ font: "base"
8
+ }
9
+
10
+ screen Dashboard {
11
+ layout stack(direction: vertical, gap: lg, padding: lg) {
12
+ component Topbar title: "Dashboard" subtitle: "Main view"
13
+ component StatCard title: "Count" value: "42"
14
+ }
15
+ }
16
+
17
+ screen Settings {
18
+ layout stack(direction: vertical, gap: lg, padding: lg) {
19
+ component Topbar title: "Settings"
20
+ component Input label: "Username" placeholder: "user@example.com"
21
+ }
22
+ }
23
+
24
+ screen Profile {
25
+ layout stack(direction: vertical, gap: lg, padding: lg) {
26
+ component Topbar title: "Profile" subtitle: "User info"
27
+ component Checkbox label: "Notifications enabled"
28
+ }
29
+ }
30
+ }
package/dist/index.html CHANGED
@@ -5,8 +5,8 @@
5
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>WireDSL - Wireframes as Code</title>
8
- <script type="module" crossorigin src="/assets/index-CHiOjnNN.js"></script>
9
- <link rel="stylesheet" crossorigin href="/assets/index-CUIy2zPc.css">
8
+ <script type="module" crossorigin src="/assets/index-C6yQ9VSx.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-CmAJnnOw.css">
10
10
  </head>
11
11
  <body>
12
12
  <div id="root"></div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wire-dsl/web",
3
- "version": "0.0.7",
3
+ "version": "0.1.0",
4
4
  "description": "WireDSL Web - Live editor with React and Monaco",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -14,7 +14,9 @@
14
14
  "@radix-ui/react-dialog": "1.1.15",
15
15
  "@radix-ui/react-slot": "1.2.4",
16
16
  "lucide-react": "0.562.0",
17
- "@wire-dsl/core": "0.1.5"
17
+ "@wire-dsl/engine": "0.0.2",
18
+ "@wire-dsl/editor-ui": "0.0.1",
19
+ "@wire-dsl/language-support": "0.0.2"
18
20
  },
19
21
  "devDependencies": {
20
22
  "@tailwindcss/postcss": "4.1.18",
@@ -36,7 +38,7 @@
36
38
  },
37
39
  "scripts": {
38
40
  "dev": "vite",
39
- "build": "tsc && vite build",
41
+ "build": "vite build",
40
42
  "preview": "vite preview",
41
43
  "type-check": "tsc --noEmit",
42
44
  "lint": "eslint src --ext .ts,.tsx",
@@ -1,5 +1,7 @@
1
1
  export default {
2
2
  plugins: {
3
- '@tailwindcss/postcss': {}
3
+ '@tailwindcss/postcss': {
4
+ optimize: false
5
+ }
4
6
  }
5
7
  };
@@ -0,0 +1,95 @@
1
+ project "Admin Dashboard" {
2
+ theme {
3
+ density: "normal"
4
+ spacing: "md"
5
+ radius: "md"
6
+ stroke: "normal"
7
+ font: "base"
8
+ }
9
+
10
+ screen UsersList {
11
+ layout split(sidebar: 240, gap: lg) {
12
+ layout stack(direction: vertical, gap: md, padding: md) {
13
+ component Heading text: "Menu"
14
+ component SidebarMenu items: "Users,Roles,Permissions,Audit,Settings" active: 0
15
+ }
16
+
17
+ layout stack(direction: vertical, gap: lg, padding: lg) {
18
+ component Heading text: "Users"
19
+ component Text content: "Manage system users"
20
+
21
+ layout grid(columns: 12, gap: md) {
22
+ cell span: 8 {
23
+ component Input label: "Search user" placeholder: "name, email..."
24
+ }
25
+ cell span: 4 align: end {
26
+ component Button text: "Create user" variant: primary
27
+ }
28
+ }
29
+
30
+ component Table columns: "ID,Name,Email,Status,Role" rows: 8
31
+ }
32
+ }
33
+ }
34
+
35
+ screen UserDetail {
36
+ layout stack(direction: vertical, gap: lg, padding: lg) {
37
+ component Breadcrumbs items: "Users,User Details"
38
+
39
+ component Heading text: "User Details"
40
+ component Text content: "View and edit user information"
41
+
42
+ layout panel(padding: lg) {
43
+ layout stack(direction: vertical, gap: md) {
44
+ component Heading text: "Account Status"
45
+ component Text content: "User account is active and in good standing"
46
+
47
+ component Textarea label: "Bio" placeholder: "User bio and notes..." rows: 4
48
+
49
+ component Checkbox label: "Email verified"
50
+
51
+ component Toggle label: "Two-factor authentication"
52
+
53
+ component Select label: "Status" items: "Active,Inactive,Pending"
54
+
55
+ component Divider
56
+
57
+ layout stack(direction: horizontal, gap: md) {
58
+ component Button text: "Save" variant: primary
59
+ component Button text: "Cancel"
60
+ }
61
+ }
62
+ }
63
+ }
64
+ }
65
+
66
+ screen UserCreate {
67
+ layout stack(direction: vertical, gap: lg, padding: xl) {
68
+ component Heading text: "Create New User"
69
+ component Text content: "Add a new user to the system"
70
+
71
+ layout panel(padding: lg) {
72
+ layout stack(direction: vertical, gap: md) {
73
+ component Input label: "First Name" placeholder: "John"
74
+
75
+ component Input label: "Last Name" placeholder: "Doe"
76
+
77
+ component Input label: "Email Address" placeholder: "john.doe@example.com"
78
+
79
+ component Select label: "Role" items: "Admin,Editor,Viewer,Moderator,User"
80
+
81
+ component Select label: "Status" items: "Active,Inactive,Pending"
82
+
83
+ component Checkbox label: "Send welcome email"
84
+
85
+ component Checkbox label: "Require password change on first login"
86
+
87
+ layout stack(direction: horizontal, gap: md) {
88
+ component Button text: "Create User" variant: primary
89
+ component Button text: "Cancel"
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }
95
+ }
@@ -0,0 +1,65 @@
1
+ project "Analytics Dashboard" {
2
+ theme {
3
+ density: "normal"
4
+ spacing: "md"
5
+ radius: "md"
6
+ stroke: "normal"
7
+ font: "base"
8
+ }
9
+
10
+ screen Dashboard {
11
+ layout stack(direction: vertical, gap: lg, padding: xl) {
12
+ component Topbar title: "Analytics" subtitle: "Realtime overview"
13
+
14
+ layout split(sidebar: 260, gap: lg) {
15
+ layout stack(direction: vertical, gap: md, padding: md) {
16
+ component Heading title: "Filters"
17
+ component Select label: "Date Range" items: "Last 7 days,Last 30 days,Last 90 days"
18
+ component Select label: "Channel" items: "All channels,Social,Email,Direct"
19
+ component Select label: "Region" items: "Global,North America,Europe,Asia"
20
+ component Divider
21
+ component Checkbox label: "Email alerts"
22
+ component Checkbox label: "Slack alerts"
23
+ }
24
+
25
+ layout stack(direction: vertical, gap: lg, padding: lg) {
26
+ layout grid(columns: 12, gap: md) {
27
+ cell span: 3 {
28
+ component Badge text: "+12%" variant: primary
29
+ }
30
+ cell span: 3 {
31
+ component Badge text: "-3%" variant: secondary
32
+ }
33
+ cell span: 3 {
34
+ component Badge text: "4.5k" variant: primary
35
+ }
36
+ cell span: 3 {
37
+ component Badge text: "1.2k" variant: secondary
38
+ }
39
+ }
40
+
41
+ component Tabs items: "Overview,Traffic,Revenue,Engagement" activeIndex: 0
42
+
43
+ layout grid(columns: 12, gap: md) {
44
+ cell span: 6 {
45
+ component ChartPlaceholder type: "bar" height: 250
46
+ }
47
+ cell span: 6 {
48
+ component ChartPlaceholder type: "line" height: 250
49
+ }
50
+ cell span: 12 {
51
+ component ChartPlaceholder type: "area" height: 250
52
+ }
53
+ }
54
+
55
+ layout stack(direction: vertical, gap: sm) {
56
+ component Alert type: "warning" message: "Traffic spike detected on mobile devices"
57
+ component Alert type: "error" message: "Sync delayed for EU region"
58
+ }
59
+
60
+ component Table columns: "User,Country,Device,Time" rows: 10
61
+ }
62
+ }
63
+ }
64
+ }
65
+ }
@@ -0,0 +1,50 @@
1
+ project "Form Example" {
2
+ theme {
3
+ density: "normal"
4
+ spacing: "md"
5
+ radius: "md"
6
+ stroke: "normal"
7
+ font: "base"
8
+ }
9
+
10
+ screen FormScreen {
11
+ layout stack(direction: vertical, gap: md, padding: lg) {
12
+ component Heading text: "User Registration"
13
+
14
+ component Text content: "Please fill in all required fields below"
15
+
16
+ layout stack(direction: vertical, gap: md, padding: md) {
17
+ component Input label: "Full Name" placeholder: "John Doe"
18
+
19
+ component Input label: "Email" placeholder: "john@example.com"
20
+
21
+ component Textarea label: "Bio" placeholder: "Tell us about yourself..." rows: 4
22
+
23
+ component Select label: "Country" items: "USA,Canada,Mexico,UK,Spain"
24
+
25
+ layout stack(direction: vertical, gap: sm, padding: md) {
26
+ component Heading text: "Preferences"
27
+
28
+ component Checkbox label: "Subscribe to newsletter"
29
+ component Checkbox label: "Enable notifications"
30
+ }
31
+
32
+ layout stack(direction: vertical, gap: sm, padding: md) {
33
+ component Heading text: "Account Type"
34
+
35
+ component Radio label: "Personal"
36
+ component Radio label: "Business"
37
+ }
38
+
39
+ layout stack(direction: vertical, gap: md) {
40
+ component Toggle label: "Terms & Conditions"
41
+ }
42
+ }
43
+
44
+ layout stack(direction: horizontal, gap: md) {
45
+ component Button text: "Cancel"
46
+ component Button text: "Submit" variant: primary
47
+ }
48
+ }
49
+ }
50
+ }
@@ -0,0 +1,40 @@
1
+ project "Simple Dashboard" {
2
+ theme {
3
+ density: "comfortable"
4
+ spacing: "lg"
5
+ radius: "md"
6
+ stroke: "normal"
7
+ font: "base"
8
+ }
9
+
10
+ screen Dashboard {
11
+ layout stack(direction: vertical, gap: lg, padding: xl) {
12
+ component Topbar title: "Dashboard"
13
+
14
+ layout grid(columns: 12, gap: lg) {
15
+ cell span: 4 {
16
+ layout card(padding: md, gap: md) {
17
+ component Heading text: "Total Users"
18
+ component StatCard title: "Count" value: "2,543"
19
+ }
20
+ }
21
+ cell span: 4 {
22
+ layout card(padding: md, gap: md) {
23
+ component Heading text: "Active Sessions"
24
+ component StatCard title: "Active" value: "856"
25
+ }
26
+ }
27
+ cell span: 4 {
28
+ layout card(padding: md, gap: md) {
29
+ component Heading text: "Revenue"
30
+ component StatCard title: "Total" value: "$45.2K"
31
+ }
32
+ }
33
+ }
34
+
35
+ component ChartPlaceholder type: "bar" height: 300
36
+
37
+ component Table columns: "Date,Event,User" rows: 5
38
+ }
39
+ }
40
+ }
@@ -0,0 +1,30 @@
1
+ project "Admin Dashboard Simple" {
2
+ theme {
3
+ density: "normal"
4
+ spacing: "md"
5
+ radius: "md"
6
+ stroke: "normal"
7
+ font: "base"
8
+ }
9
+
10
+ screen Dashboard {
11
+ layout stack(direction: vertical, gap: lg, padding: lg) {
12
+ component Topbar title: "Dashboard" subtitle: "Main view"
13
+ component StatCard title: "Count" value: "42"
14
+ }
15
+ }
16
+
17
+ screen Settings {
18
+ layout stack(direction: vertical, gap: lg, padding: lg) {
19
+ component Topbar title: "Settings"
20
+ component Input label: "Username" placeholder: "user@example.com"
21
+ }
22
+ }
23
+
24
+ screen Profile {
25
+ layout stack(direction: vertical, gap: lg, padding: lg) {
26
+ component Topbar title: "Profile" subtitle: "User info"
27
+ component Checkbox label: "Notifications enabled"
28
+ }
29
+ }
30
+ }
package/src/App.tsx CHANGED
@@ -1,15 +1,5 @@
1
+ import { WireLiveEditor } from './components/WireLiveEditor';
2
+
1
3
  export default function App() {
2
- return (
3
- <div className="h-screen bg-slate-50 flex items-center justify-center">
4
- <div className="text-center">
5
- <h1 className="text-4xl font-bold text-slate-900 mb-4">✨ WireDSL Web Editor</h1>
6
- <p className="text-lg text-slate-600 mb-8">Wireframes as Code - Coming Soon</p>
7
- <div className="space-y-2 text-sm text-slate-500">
8
- <p>📝 Monaco Editor ready</p>
9
- <p>🎨 Tailwind CSS configured</p>
10
- <p>🚀 React 18 running</p>
11
- </div>
12
- </div>
13
- </div>
14
- );
4
+ return <WireLiveEditor />;
15
5
  }
@@ -0,0 +1,112 @@
1
+ import React, { useEffect, useRef } from 'react';
2
+ import * as monaco from 'monaco-editor';
3
+
4
+ export interface MonacoEditorProps {
5
+ content: string;
6
+ onChange: (content: string) => void;
7
+ fileName?: string;
8
+ language?: string;
9
+ readOnly?: boolean;
10
+ className?: string;
11
+ }
12
+
13
+ export const MonacoEditorComponent = React.forwardRef<
14
+ monaco.editor.IStandaloneCodeEditor | null,
15
+ MonacoEditorProps
16
+ >(
17
+ (
18
+ {
19
+ content,
20
+ onChange,
21
+ fileName = 'untitled.wire',
22
+ language = 'wire',
23
+ readOnly = false,
24
+ className = '',
25
+ },
26
+ ref
27
+ ) => {
28
+ const containerRef = useRef<HTMLDivElement>(null);
29
+ const editorRef = useRef<monaco.editor.IStandaloneCodeEditor | null>(null);
30
+ const isInitializedRef = useRef(false);
31
+
32
+ // Inicializar Monaco Editor - solo una vez
33
+ useEffect(() => {
34
+ if (!containerRef.current || isInitializedRef.current) return;
35
+
36
+ try {
37
+ const editor = monaco.editor.create(containerRef.current, {
38
+ value: content,
39
+ language,
40
+ theme: 'vs-light',
41
+ fontSize: 14,
42
+ fontFamily: 'Fira Code, monospace',
43
+ lineNumbers: 'on',
44
+ wordWrap: 'on',
45
+ autoClosingBrackets: 'always',
46
+ autoClosingQuotes: 'always',
47
+ autoIndent: 'full',
48
+ formatOnPaste: true,
49
+ tabSize: 2,
50
+ insertSpaces: true,
51
+ readOnly,
52
+ minimap: { enabled: true },
53
+ scrollBeyondLastLine: false,
54
+ automaticLayout: true,
55
+ });
56
+
57
+ editorRef.current = editor;
58
+ isInitializedRef.current = true;
59
+
60
+ // Actualizar ref para acceso desde el parent
61
+ if (typeof ref === 'function') {
62
+ ref(editor);
63
+ } else if (ref) {
64
+ ref.current = editor;
65
+ }
66
+ } catch (error) {
67
+ console.error('Error creating Monaco editor:', error);
68
+ }
69
+ }, []);
70
+
71
+ // Setup listener - separado, se ejecuta cada vez que onChange cambia
72
+ useEffect(() => {
73
+ if (!editorRef.current) return;
74
+
75
+ const disposable = editorRef.current.onDidChangeModelContent(() => {
76
+ const newContent = editorRef.current!.getValue();
77
+ onChange(newContent);
78
+ });
79
+
80
+ return () => {
81
+ disposable.dispose();
82
+ };
83
+ }, [onChange]);
84
+
85
+ // Actualizar contenido cuando el prop cambia externamente
86
+ useEffect(() => {
87
+ if (
88
+ editorRef.current &&
89
+ editorRef.current.getValue() !== content
90
+ ) {
91
+ editorRef.current.setValue(content);
92
+ }
93
+ }, [content]);
94
+
95
+ return (
96
+ <div
97
+ ref={containerRef}
98
+ className={className}
99
+ style={{
100
+ display: 'flex',
101
+ width: '100%',
102
+ height: '100%',
103
+ backgroundColor: '#ffffff',
104
+ }}
105
+ />
106
+ );
107
+ }
108
+ );
109
+
110
+ MonacoEditorComponent.displayName = 'MonacoEditorComponent';
111
+
112
+ MonacoEditorComponent.displayName = 'MonacoEditorComponent';