@breakside/jskit 2025.36.0 → 2025.40.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 (51) hide show
  1. package/Frameworks/DOM.jsframework/Info.json +2 -2
  2. package/Frameworks/DOM.jsframework/io.breakside.JSKit.DOM-bundle.js +2 -2
  3. package/Frameworks/FontKit.jsframework/Info.json +2 -2
  4. package/Frameworks/FontKit.jsframework/io.breakside.JSKit.FontKit-bundle.js +2 -2
  5. package/Frameworks/Foundation.jsframework/Info.json +2 -2
  6. package/Frameworks/Foundation.jsframework/io.breakside.JSKit.Foundation-bundle.js +2 -2
  7. package/Frameworks/SecurityKit.jsframework/Info.json +2 -2
  8. package/Frameworks/SecurityKit.jsframework/io.breakside.JSKit.SecurityKit-bundle.js +2 -2
  9. package/Info.json +2 -2
  10. package/Node/HTMLProjectServer.js +12 -1
  11. package/Node/Printer.js +11 -0
  12. package/Node/Resources.js +5 -3
  13. package/Node/io.breakside.jskit-bundle.js +2 -2
  14. package/Root/Frameworks/APIKit/Info.yaml +1 -1
  15. package/Root/Frameworks/APIKitTesting/Info.yaml +1 -1
  16. package/Root/Frameworks/AuthKit/Info.yaml +1 -1
  17. package/Root/Frameworks/CSSOM/Info.yaml +1 -1
  18. package/Root/Frameworks/ChartKit/Info.yaml +1 -1
  19. package/Root/Frameworks/ConferenceKit/Info.yaml +1 -1
  20. package/Root/Frameworks/DBKit/Info.yaml +1 -1
  21. package/Root/Frameworks/DOM/Info.yaml +1 -1
  22. package/Root/Frameworks/Dispatch/Info.yaml +1 -1
  23. package/Root/Frameworks/FontKit/Info.yaml +1 -1
  24. package/Root/Frameworks/Foundation/Info.yaml +1 -1
  25. package/Root/Frameworks/ImageKit/Info.yaml +1 -1
  26. package/Root/Frameworks/MediaKit/Info.yaml +1 -1
  27. package/Root/Frameworks/MediaKitUI/Info.yaml +1 -1
  28. package/Root/Frameworks/NotificationKit/Info.yaml +1 -1
  29. package/Root/Frameworks/PDFKit/Info.yaml +1 -1
  30. package/Root/Frameworks/QRKit/Info.yaml +1 -1
  31. package/Root/Frameworks/SearchKit/Info.yaml +1 -1
  32. package/Root/Frameworks/SecurityKit/Info.yaml +1 -1
  33. package/Root/Frameworks/ServerKit/Info.yaml +1 -1
  34. package/Root/Frameworks/ServerKitTesting/Info.yaml +1 -1
  35. package/Root/Frameworks/TestKit/Info.yaml +1 -1
  36. package/Root/Frameworks/UIKit/Info.yaml +1 -1
  37. package/Root/Frameworks/UIKit/UIAccessibility.js +1 -0
  38. package/Root/Frameworks/UIKit/UIContainerView.js +6 -1
  39. package/Root/Frameworks/UIKit/UIHTMLDisplayServerCanvasContext.js +5 -2
  40. package/Root/Frameworks/UIKit/UIListView.js +7 -1
  41. package/Root/Frameworks/UIKit/UIPopupButton.js +2 -0
  42. package/Root/Frameworks/UIKit/UIScrollView.js +7 -2
  43. package/Root/Frameworks/UIKit/UISplitView.js +2 -2
  44. package/Root/Frameworks/UIKit/UIStackView.js +5 -0
  45. package/Root/Frameworks/UIKit/UITabView.js +15 -3
  46. package/Root/Frameworks/UIKit/UITextEditor.js +3 -0
  47. package/Root/Frameworks/UIKit/UITextField.js +11 -7
  48. package/Root/Frameworks/UIKit/UIToolbar.js +14 -1
  49. package/Root/Frameworks/UIKit/UIView.js +10 -0
  50. package/Root/Frameworks/UIKitTesting/Info.yaml +1 -1
  51. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
4
- "JSBundleVersion": "2025.36.0",
4
+ "JSBundleVersion": "2025.40.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "DOM+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
12
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.DOM",
6
- "JSBundleVersion": "2025.36.0",
6
+ "JSBundleVersion": "2025.40.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.DOM'] = {
11
11
  "node": "DOM+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
14
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
4
- "JSBundleVersion": "2025.36.0",
4
+ "JSBundleVersion": "2025.40.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
8
8
  "html": "FontKit+HTML.js"
9
9
  },
10
10
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
11
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
11
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
12
12
  }
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.JSKit.FontKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.FontKit",
6
- "JSBundleVersion": "2025.36.0",
6
+ "JSBundleVersion": "2025.40.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
10
10
  "html": "FontKit+HTML.js"
11
11
  },
12
12
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
13
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
13
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
14
14
  },
15
15
  "Resources": [],
16
16
  "ResourceLookup": {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
4
- "JSBundleVersion": "2025.36.0",
4
+ "JSBundleVersion": "2025.40.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "Foundation+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
12
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.Foundation",
6
- "JSBundleVersion": "2025.36.0",
6
+ "JSBundleVersion": "2025.40.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.Foundation'] = {
11
11
  "node": "Foundation+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
14
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
15
15
  },
16
16
  "Resources": [
17
17
  {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "JSBundleType": "framework",
3
3
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
4
- "JSBundleVersion": "2025.36.0",
4
+ "JSBundleVersion": "2025.40.0",
5
5
  "JSDevelopmentLanguage": "en",
6
6
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
7
7
  "JSBundleEnvironments": {
@@ -9,5 +9,5 @@
9
9
  "node": "SecurityKit+Node.js"
10
10
  },
11
11
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
12
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
12
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
13
13
  }
@@ -3,7 +3,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "framework",
5
5
  "JSBundleIdentifier": "io.breakside.JSKit.SecurityKit",
6
- "JSBundleVersion": "2025.36.0",
6
+ "JSBundleVersion": "2025.40.0",
7
7
  "JSDevelopmentLanguage": "en",
8
8
  "JSCopyright": "Copyright © 2020 Breakside Inc.",
9
9
  "JSBundleEnvironments": {
@@ -11,7 +11,7 @@ JSBundle.bundles['io.breakside.JSKit.SecurityKit'] = {
11
11
  "node": "SecurityKit+Node.js"
12
12
  },
13
13
  "JSLicenseNotice": "Licensed under the Breakside Public License, Version 1.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nIf a copy of the License was not distributed with this file, you may\nobtain a copy at\n\n http://breakside.io/licenses/LICENSE-1.0.txt\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n",
14
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
14
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
15
15
  },
16
16
  "Resources": [],
17
17
  "ResourceLookup": {
package/Info.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "JSBundleType": "node",
3
3
  "JSBundleIdentifier": "io.breakside.jskit",
4
- "JSBundleVersion": "2025.36.0",
4
+ "JSBundleVersion": "2025.40.0",
5
5
  "JSExecutableName": "jskit",
6
6
  "NPMOrganization": "breakside",
7
7
  "JSResources": [
8
8
  "Tests/HTMLTestRunner.js",
9
9
  "Tests/NodeTestRunner.js"
10
10
  ],
11
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
11
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
12
12
  }
@@ -101,6 +101,11 @@ JSClass("HTMLProjectServer", JSObject, {
101
101
 
102
102
  alwaysExpires: JSLazyInitProperty(() => "Thu, 01 Jan 1970 00:00:01 GMT"),
103
103
  neverExpires: JSLazyInitProperty(() => "Thu, 31 Dec 2037 23:55:55 GMT"),
104
+ ingored404URLs: JSLazyInitProperty(() => new Set([
105
+ "/favicon.ico",
106
+ "/apple-touch-icon.png",
107
+ "/apple-touch-icon-precomposed.png"
108
+ ])),
104
109
 
105
110
  _handleNodeRequest: async function(nodeRequest, nodeResponse){
106
111
  let statusCode = null;
@@ -178,6 +183,7 @@ JSClass("HTMLProjectServer", JSObject, {
178
183
  statusCode = 404;
179
184
  }
180
185
  }catch (e){
186
+ this.printer.ensureNewline();
181
187
  logger.error("Error handling request: %{error}", e);
182
188
  statusCode = 500;
183
189
  }
@@ -186,6 +192,7 @@ JSClass("HTMLProjectServer", JSObject, {
186
192
  try{
187
193
  nodeResponse.writeHead(statusCode, headers);
188
194
  }catch (e){
195
+ this.printer.ensureNewline();
189
196
  logger.error("Error sending response headers: %{error}", e);
190
197
  nodeResponse.writeHead(500);
191
198
  }
@@ -198,10 +205,14 @@ JSClass("HTMLProjectServer", JSObject, {
198
205
  nodeResponse.end();
199
206
  }
200
207
  if (statusCode >= 400){
201
- logger.warn("%d %{public} %{public}", statusCode, nodeRequest.method, nodeRequest.url);
208
+ if (statusCode !== 404 || !this.ingored404URLs.has(nodeRequest.url)){
209
+ this.printer.ensureNewline();
210
+ logger.warn("%d %{public} %{public}", statusCode, nodeRequest.method, nodeRequest.url);
211
+ }
202
212
  }
203
213
  }catch (e){
204
214
  nodeRequest.socket.destroy();
215
+ this.printer.ensureNewline();
205
216
  logger.error("Error sending response: %{error}", e);
206
217
  }
207
218
  },
package/Node/Printer.js CHANGED
@@ -75,8 +75,19 @@ JSClass("Printer", JSObject, {
75
75
  }
76
76
  },
77
77
 
78
+ atNewline: true,
79
+
80
+ ensureNewline: function(){
81
+ if (!this.atNewline){
82
+ this._printRawData("\n".utf8());
83
+ }
84
+ },
85
+
78
86
  _printRawData: function(data){
79
87
  this.stream.write(data);
88
+ if (data.length > 0){
89
+ this.atNewline = data[data.length - 1] == 0x0A;
90
+ }
80
91
  },
81
92
 
82
93
  _erase: function(count){
package/Node/Resources.js CHANGED
@@ -50,7 +50,7 @@ JSClass("Resources", JSObject, {
50
50
 
51
51
  getImportPaths: async function(importDirectoryURLs){
52
52
  var fileManager = this.fileManager;
53
- var addImportsFromObject = async function(obj){
53
+ var addImportsFromObject = async function(obj, debugPath){
54
54
  if (typeof(obj) == "object"){
55
55
  if ('class' in obj){
56
56
  let path = obj['class'] + '.js';
@@ -97,7 +97,9 @@ JSClass("Resources", JSObject, {
97
97
  }
98
98
  for (let k in obj){
99
99
  if (k == 'class' || k == 'include') continue;
100
- await addImportsFromObject(obj[k]);
100
+ if (obj[k] !== null){
101
+ await addImportsFromObject(obj[k], debugPath.concat([k]));
102
+ }
101
103
  }
102
104
  }
103
105
  };
@@ -119,7 +121,7 @@ JSClass("Resources", JSObject, {
119
121
  for (let i = 0, l = this.metadata.length; i < l; ++i){
120
122
  let metadata = this.metadata[i];
121
123
  if (metadata.spec){
122
- await addImportsFromObject(metadata.value);
124
+ await addImportsFromObject(metadata.value, [metadata.path]);
123
125
  }
124
126
  }
125
127
  return Array.from(paths.values());
@@ -3,14 +3,14 @@ JSBundle.bundles['io.breakside.jskit'] = {
3
3
  "Info": {
4
4
  "JSBundleType": "node",
5
5
  "JSBundleIdentifier": "io.breakside.jskit",
6
- "JSBundleVersion": "2025.36.0",
6
+ "JSBundleVersion": "2025.40.0",
7
7
  "JSExecutableName": "jskit",
8
8
  "NPMOrganization": "breakside",
9
9
  "JSResources": [
10
10
  "Tests/HTMLTestRunner.js",
11
11
  "Tests/NodeTestRunner.js"
12
12
  ],
13
- "GitRevision": "542d9c51b5664a6f0e1a92bdb945534a06c433ea"
13
+ "GitRevision": "b27f6da2abb9e485747019567c0a74d7c08fd120"
14
14
  },
15
15
  "Resources": [
16
16
  {
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSIncludeDirectories:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.APIKitTesting
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.AuthKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.CSSOM
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ChartKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2021 Breakside Inc.
6
6
  # JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ConferenceKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.DBKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.DOM
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.Dispatch
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSCopyright: Copyright © 2020 Breakside Inc.
5
5
  JSBundleEnvironments:
6
6
  html: Dispatch+HTML.js
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.FontKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.Foundation
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ImageKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.MediaKitUI
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.NotificationKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2021 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.PDFKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.QRKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SearchKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.SecurityKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.ServerKitTesting
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.TestKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKit
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSBundleEnvironments:
@@ -53,6 +53,7 @@ JSProtocol("UIAccessibility", JSProtocol, {
53
53
  // Properties
54
54
  accessibilityTextualContext: null,
55
55
  accessibilityMenu: null,
56
+ accessibilityDraggable: false,
56
57
 
57
58
  // Children
58
59
  accessibilityParent: null,
@@ -105,6 +105,11 @@ JSClass("UIContainerView", UIView, {
105
105
  );
106
106
  },
107
107
 
108
+ subviewDidInvalidateSize: function(subview){
109
+ this.setNeedsLayout();
110
+ this.invalidateSize();
111
+ },
112
+
108
113
  sizeToFitSize: function(maxSize){
109
114
  if (this._contentView === null){
110
115
  UIContainerView.$super.sizeToFitSize.call(this, maxSize);
@@ -128,7 +133,7 @@ JSClass("UIContainerView", UIView, {
128
133
  var rect = this.bounds.rectWithInsets(this._contentInsets);
129
134
  if (this._contentView !== null){
130
135
  if (this._alignment === UIContainerView.Alignment.full){
131
- this._contentView.frame = rect;
136
+ this._contentView.untransformedFrame = rect;
132
137
  }else if (this._alignment === UIContainerView.Alignment.center){
133
138
  var maxSize = JSSize(rect.size);
134
139
  if (this._maximumContentSize.width > 0 && this._maximumContentSize.width < maxSize.width){
@@ -953,8 +953,11 @@ JSClass("UIHTMLDisplayServerCanvasContext", UIHTMLDisplayServerContext, {
953
953
  };
954
954
  this.accessibilityMousedownListener = function(e){
955
955
  // We don't want mousedown to focus the element
956
- // Unfortunately, this prevents the element from working with drag and drop
957
- e.preventDefault();
956
+ // Unfortunately, this prevents the element from working with drag and drop,
957
+ // So elements can opt-in to allowing drag by allowing focus-on-mousedown
958
+ if (!accessibility.accessibilityDraggable){
959
+ e.preventDefault();
960
+ }
958
961
  };
959
962
  this.element.addEventListener("focus", this.accessibilityFocusListener);
960
963
  this.element.addEventListener("mousedown", this.accessibilityMousedownListener);
@@ -3384,7 +3384,13 @@ JSClass("UIListViewDefaultStyler", UIListViewStyler, {
3384
3384
  if (cell._accessoryView !== null){
3385
3385
  var accessorySize = this.accessorySize;
3386
3386
  if (accessorySize === null){
3387
- accessorySize = cell._accessoryView.intrinsicSize;
3387
+ accessorySize = JSSize(cell._accessoryView.intrinsicSize);
3388
+ if (accessorySize.width === UIView.noIntrinsicSize){
3389
+ accessorySize.width = cell._accessoryView.bounds.size.width;
3390
+ }
3391
+ if (accessorySize.height === UIView.noIntrinsicSize){
3392
+ accessorySize.height = cell._accessoryView.bounds.size.height;
3393
+ }
3388
3394
  }
3389
3395
  cell._accessoryView.frame = JSRect(cell._contentView.bounds.size.width - cell._accessoryInsets.right - accessorySize.width, (cell._contentView.bounds.size.height - accessorySize.height) / 2, accessorySize.width, accessorySize.height);
3390
3396
  size.width -= accessorySize.width + cell._accessoryInsets.width;
@@ -286,6 +286,7 @@ JSClass("UIPopupButton", UIControl, {
286
286
  this.menu.font = this.titleLabel.font;
287
287
  }
288
288
  this.menu.delegate = this;
289
+ this.sendActionsForEvents(UIControl.Event.editingDidBegin);
289
290
  if (this._pullsDown){
290
291
  this.menu.minimumWidth = this.frame.size.width;
291
292
  this.menu.openAdjacentToView(this, UIMenu.Placement.below, 1);
@@ -318,6 +319,7 @@ JSClass("UIPopupButton", UIControl, {
318
319
  this.menu.delegate = null;
319
320
  this.menu.accessibilityParent = null;
320
321
  this._isMenuOpen = false;
322
+ this.sendActionsForEvents(UIControl.Event.editingDidEnd);
321
323
  },
322
324
 
323
325
  setSelectedIndex: function(index){
@@ -44,7 +44,7 @@ JSClass('UIScrollView', UIView, {
44
44
  // These properties are optional in the spec, and are typically only provided if
45
45
  // the user wants to provide specialized customization
46
46
  if (spec.containsKey('contentView')){
47
- this._contentView = spec.valueForKey("contentView", UIView);
47
+ this._contentView = spec.valueForKey("contentView", this.contentViewClass);
48
48
  }else{
49
49
  // If any subviews were added directly to this view, and a
50
50
  // contentView was not provided, treat the subviews as children
@@ -84,15 +84,20 @@ JSClass('UIScrollView', UIView, {
84
84
  if (spec.containsKey('delaysContentTouches')){
85
85
  this._delaysContentTouches = spec.valueForKey("delaysContentTouches");
86
86
  }
87
+ if (spec.containsKey('delegate')){
88
+ this.delegate = spec.valueForKey('delegate');
89
+ }
87
90
  },
88
91
 
92
+ contentViewClass: UIView,
93
+
89
94
  _commonScrollViewInit: function(){
90
95
  this.clipsToBounds = true;
91
96
 
92
97
  // Only create the content view and scrollers if the haven't already been created
93
98
  // by a specialized init function like initWithSpec.
94
99
  if (this._contentView === null){
95
- this._contentView = UIView.initWithFrame(this.bounds);
100
+ this._contentView = this.contentViewClass.initWithFrame(this.bounds);
96
101
  }
97
102
  if (this._horizontalScroller === null){
98
103
  this._horizontalScroller = UIScroller.initWithDirection(UIScroller.Direction.horizontal, this._scrollStyler);
@@ -487,7 +487,7 @@ JSClass("UISplitView", UIView, {
487
487
  }
488
488
  if (divider === this._leadingDividerView){
489
489
  var maximumLeadingSize = boundsSize - this._minimumMainSize;
490
- if (this._trailingViewOpen){
490
+ if (this._trailingViewOpen && this._trailingView !== null){
491
491
  maximumLeadingSize -= this._trailingSize;
492
492
  }
493
493
  if (this._maximumLeadingSize < maximumLeadingSize){
@@ -517,7 +517,7 @@ JSClass("UISplitView", UIView, {
517
517
  }
518
518
  }else if (divider === this._trailingDividerView){
519
519
  var maximumTrailingSize = boundsSize - this._minimumMainSize;
520
- if (this._leadingViewOpen){
520
+ if (this._leadingViewOpen && this._leadingView !== null){
521
521
  maximumTrailingSize -= this._leadingSize;
522
522
  }
523
523
  if (this._maximumTrailingSize < maximumTrailingSize){
@@ -217,6 +217,11 @@ JSClass("UIStackView", UIView, {
217
217
  this.setNeedsLayout();
218
218
  },
219
219
 
220
+ subviewDidInvalidateSize: function(subview){
221
+ this.setNeedsLayout();
222
+ this.invalidateSize();
223
+ },
224
+
220
225
  getFirstBaselineOffsetFromTop: function(){
221
226
  var top = this._contentInsets.top;
222
227
  if (this._arrangedSubviews.length > 0){
@@ -421,7 +421,19 @@ JSClass("UITabViewItemView", UIView, {
421
421
 
422
422
  canBecomeFirstResponder: function(){
423
423
  return this.fullKeyboardAccessEnabled;
424
- }
424
+ },
425
+
426
+ mouseEntered: function(event){
427
+ var tabView = this.superview.tabView;
428
+ tabView.items[this.index].over = true;
429
+ tabView._styler.updateTabViewItemAtIndex(tabView, this.index);
430
+ },
431
+
432
+ mouseExited: function(event){
433
+ var tabView = this.superview.tabView;
434
+ tabView.items[this.index].over = false;
435
+ tabView._styler.updateTabViewItemAtIndex(tabView, this.index);
436
+ },
425
437
 
426
438
  });
427
439
 
@@ -717,8 +729,8 @@ JSClass("UITabViewDefaultStyler", UITabViewStyler, {
717
729
  if (spec.containsKey("itemContentInsets")){
718
730
  this.itemContentInsets = spec.valueForKey("itemContentInsets", JSInsets);
719
731
  }
720
- if (spec.containsKey("itemInsets")){
721
- this.itemInsets = spec.valueForKey("itemInsets", JSInsets);
732
+ if (spec.containsKey("itemsInsets")){
733
+ this.itemsInsets = spec.valueForKey("itemsInsets", JSInsets);
722
734
  }
723
735
  if (spec.containsKey("dividerColor")){
724
736
  this.dividerColor = spec.valueForKey("dividerColor", JSColor);
@@ -760,7 +760,9 @@ JSClass("UITextEditor", JSObject, {
760
760
  }
761
761
  this.undoManager.registerUndo(this, this._replaceTextStorageRangeAllowingUndo, textStorage, JSRange(range.location, insertedLength), replacedString);
762
762
  this._isHandlingSelectionAdjustments = true;
763
+ this._isHandlingUserAction = true;
763
764
  textStorage.replaceCharactersInRangeWithAttributedString(range, attributedString);
765
+ this._isHandlingUserAction = false;
764
766
  this._isHandlingSelectionAdjustments = false;
765
767
  },
766
768
 
@@ -817,6 +819,7 @@ JSClass("UITextEditor", JSObject, {
817
819
  },
818
820
 
819
821
  _isHandlingSelectionAdjustments: false,
822
+ _isHandlingUserAction: false,
820
823
 
821
824
  textStorageDidReplaceCharactersInRange: function(range, insertedLength){
822
825
  if (!this._isHandlingSelectionAdjustments){
@@ -799,13 +799,17 @@ JSClass("UITextField", UIControl, {
799
799
  }else if (!this._isEmpty && insertedLength === 0 && !this._textLayer.hasText()){
800
800
  this._updateIsEmpty(true);
801
801
  }
802
- this.didChangeValueForBinding('text');
803
- this.didChangeValueForBinding('attributedText');
804
- this.didChangeValueForBinding('integerValue');
805
- this.postAccessibilityNotification(UIAccessibility.Notification.valueChanged);
806
- this.sendActionsForEvents(UIControl.Event.editingChanged);
807
- if (this.delegate && this.delegate.textFieldDidChange){
808
- this.delegate.textFieldDidChange(this);
802
+ if (textEditor._isHandlingUserAction){
803
+ this.didChangeValueForBinding('text');
804
+ this.didChangeValueForBinding('attributedText');
805
+ this.didChangeValueForBinding('integerValue');
806
+ this.postAccessibilityNotification(UIAccessibility.Notification.valueChanged);
807
+ this.sendActionsForEvents(UIControl.Event.editingChanged);
808
+ if (this.delegate && this.delegate.textFieldDidChange){
809
+ this.delegate.textFieldDidChange(this);
810
+ }
811
+ }else{
812
+ this.postAccessibilityNotification(UIAccessibility.Notification.valueChanged);
809
813
  }
810
814
  this._didChange = true;
811
815
  if (this._textLayer.textAlignment !== JSTextAlignment.left){
@@ -158,6 +158,19 @@ JSClass("UIToolbar", UIView, {
158
158
  return this._styler.intrinsicSizeOfToolbar(this);
159
159
  },
160
160
 
161
+ sizeToFitSize: function(maxSize){
162
+ var size = JSSize(this.intrinsicSize);
163
+ if (size.width === UIView.noIntrinsicSize){
164
+ size.width = maxSize.width;
165
+ }else if (size.width > maxSize.width){
166
+ size.width = maxSize.width;
167
+ }
168
+ if (size.height > maxSize.height){
169
+ size.height = maxSize.height;
170
+ }
171
+ this.bounds = JSRect(JSPoint.Zero, size);
172
+ },
173
+
161
174
  // --------------------------------------------------------------------
162
175
  // MARK: - Accessibility
163
176
 
@@ -678,7 +691,7 @@ JSClass("UIToolbarCustomStyler", UIToolbarStyler, {
678
691
  size = props.overflowButton.intrinsicSize;
679
692
  props.overflowButton.frame = JSRect(toolbar.bounds.size.width - this.contentInsets.right - size.width, y + (maxHeight - size.height) / 2.0, size.width, size.height);
680
693
  // reduce available width by overflow button width
681
- availableWidth -= props.overflowButton.bounds.size.width - this.itemSpacing;
694
+ availableWidth -= props.overflowButton.bounds.size.width + this.itemSpacing;
682
695
  // Back up over any overflowing items
683
696
  for (; props.lastVisibleIndex >= 0 && itemsWidth > availableWidth; --props.lastVisibleIndex){
684
697
  size = itemSizes[props.lastVisibleIndex];
@@ -583,6 +583,15 @@ JSClass('UIView', UIResponder, {
583
583
  this._needsIntrinsicSizeConstraintUpdate = true;
584
584
  },
585
585
 
586
+ invalidateSize: function(){
587
+ if (this.superview !== null){
588
+ this.superview.subviewDidInvalidateSize(this);
589
+ }
590
+ },
591
+
592
+ subviewDidInvalidateSize: function(subview){
593
+ },
594
+
586
595
  layerDidChangeSize: function(layer){
587
596
  if (layer === this.layer){
588
597
  this.invalidateFocusRingPath();
@@ -1137,6 +1146,7 @@ JSClass('UIView', UIResponder, {
1137
1146
  accessibilityEnabled: null,
1138
1147
  accessibilityLevel: null,
1139
1148
  accessibilityMultiline: null,
1149
+ accessibilityDraggable: false,
1140
1150
 
1141
1151
  // Children
1142
1152
  accessibilityParent: JSReadOnlyProperty(),
@@ -1,6 +1,6 @@
1
1
  JSBundleType: framework
2
2
  JSBundleIdentifier: io.breakside.JSKit.UIKitTesting
3
- JSBundleVersion: 2025.36.0
3
+ JSBundleVersion: 2025.40.0
4
4
  JSDevelopmentLanguage: en
5
5
  JSCopyright: Copyright © 2020 Breakside Inc.
6
6
  JSLicenseNotice: |
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "node": ">=10.10.0"
10
10
  },
11
11
  "name": "@breakside/jskit",
12
- "version": "2025.36.0",
12
+ "version": "2025.40.0",
13
13
  "license": "SEE LICENSE IN LICENSE.txt",
14
14
  "files": [
15
15
  "*"