From 50a6ab67843122452cdc3348031d44116992d492 Mon Sep 17 00:00:00 2001 From: Aylur Date: Thu, 11 Jul 2024 16:12:06 +0200 Subject: few touchups --- gjs/.eslintrc.yml | 12 --- gjs/.gitignore | 5 +- gjs/index.ts | 2 +- gjs/package-lock.json | 240 ++++++++----------------------------------------- gjs/package.json | 29 +++++- gjs/src/application.ts | 2 +- gjs/src/astalify.ts | 2 +- gjs/src/file.ts | 2 +- gjs/src/widgets.ts | 17 +++- gjs/tsconfig.json | 20 ++--- 10 files changed, 96 insertions(+), 235 deletions(-) (limited to 'gjs') diff --git a/gjs/.eslintrc.yml b/gjs/.eslintrc.yml index bb0abc7..e4309b0 100644 --- a/gjs/.eslintrc.yml +++ b/gjs/.eslintrc.yml @@ -16,15 +16,6 @@ rules: "@typescript-eslint/ban-ts-comment": error "@typescript-eslint/no-explicit-any": off "@typescript-eslint/no-non-null-assertion": off - # "@typescript-eslint/no-unused-vars": - # - error - # - varsIgnorePattern: (^unused|_$) - # argsIgnorePattern: ^(unused|_) - # "@typescript-eslint/no-empty-interface": off - # "@typescript-eslint/no-namespace": off - # "@typescript-eslint/prefer-namespace-keyword": off - # "@typescript-eslint/ban-types": off - # arrow-parens: - error - as-needed @@ -81,7 +72,6 @@ rules: max-len: - error - code: 100 - func-call-spacing: - error array-bracket-spacing: @@ -101,8 +91,6 @@ rules: globals: globalThis: readonly imports: readonly - log: readonly - logError: readonly print: readonly printerr: readonly console: readonly diff --git a/gjs/.gitignore b/gjs/.gitignore index 3ab63b7..8c2cc59 100644 --- a/gjs/.gitignore +++ b/gjs/.gitignore @@ -1,4 +1,3 @@ -node_modules -result -@girs/ +node_modules/ +result/ dist/ diff --git a/gjs/index.ts b/gjs/index.ts index 2ed6f7f..901b264 100644 --- a/gjs/index.ts +++ b/gjs/index.ts @@ -7,7 +7,7 @@ export * from "./src/file.js" export { bind, default as Binding } from "./src/binding.js" export { Variable } from "./src/variable.js" export * as Widget from "./src/widgets.js" -export { App } from "./src/application.js" +export { default as App } from "./src/application.js" // gjs crashes if a widget is constructed before Gtk.init Gtk.init(null) diff --git a/gjs/package-lock.json b/gjs/package-lock.json index cab1280..7245a27 100644 --- a/gjs/package-lock.json +++ b/gjs/package-lock.json @@ -7,12 +7,23 @@ "": { "name": "astal", "version": "0.1.0", + "license": "GPL", + "os": [ + "linux" + ], "devDependencies": { "@ts-for-gir/cli": "^3.3.0", "@typescript-eslint/eslint-plugin": "^5.33.0", "@typescript-eslint/parser": "^5.33.0", "eslint": "^8.42.0", "typescript": "^5.1.0" + }, + "engines": { + "gjs": ">=1.79.0" + }, + "funding": { + "type": "kofi", + "url": "https://ko-fi.com/aylur" } }, "node_modules/@babel/code-frame": { @@ -139,9 +150,9 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.10.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", - "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -223,18 +234,6 @@ "node": ">=18" } }, - "node_modules/@ljharb/through": { - "version": "2.3.13", - "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", - "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -553,9 +552,9 @@ "dev": true }, "node_modules/acorn": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", - "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -744,25 +743,6 @@ "ieee754": "^1.1.13" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -972,23 +952,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -1052,27 +1015,6 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/escalade": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", @@ -1463,15 +1405,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -1481,25 +1414,6 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -1580,18 +1494,6 @@ "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", "dev": true }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -1607,54 +1509,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1739,43 +1593,28 @@ "dev": true }, "node_modules/inquirer": { - "version": "9.2.23", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.23.tgz", - "integrity": "sha512-kod5s+FBPIDM2xiy9fu+6wdU/SkK5le5GS9lh4FEBjBHqiMgD9lLFbCbuqFNAjNL2ZOy9Wd9F694IOzN9pZHBA==", + "version": "9.3.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.3.5.tgz", + "integrity": "sha512-SVRCRovA7KaT6nqWB2mCNpTvU4cuZ0hOXo5KPyiyOcNNUIZwq/JKtvXuDJNaxfuJKabBYRu1ecHze0YEwDYoRQ==", "dev": true, "dependencies": { "@inquirer/figures": "^1.0.3", - "@ljharb/through": "^2.3.13", "ansi-escapes": "^4.3.2", - "chalk": "^5.3.0", - "cli-cursor": "^3.1.0", "cli-width": "^4.1.0", "external-editor": "^3.1.0", - "lodash": "^4.17.21", "mute-stream": "1.0.0", "ora": "^5.4.1", "run-async": "^3.0.0", "rxjs": "^7.8.1", "string-width": "^4.2.3", "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0" + "wrap-ansi": "^6.2.0", + "yoctocolors-cjs": "^2.1.2" }, "engines": { "node": ">=18" } }, - "node_modules/inquirer/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -2433,23 +2272,6 @@ "node": ">=10" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -2643,9 +2465,9 @@ } }, "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -2770,6 +2592,18 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/yoctocolors-cjs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz", + "integrity": "sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } } } diff --git a/gjs/package.json b/gjs/package.json index 96e5d10..b632eb4 100644 --- a/gjs/package.json +++ b/gjs/package.json @@ -3,6 +3,33 @@ "version": "0.1.0", "description": "Building blocks for buildin linux desktop shell", "type": "module", + "author": "Aylur", + "license": "GPL", + "repository": { + "type": "git", + "url": "https://github.com/astal-sh/libastal.git", + "directory": "gjs" + }, + "funding": { + "type": "kofi", + "url": "https://ko-fi.com/aylur" + }, + "exports": { + ".": "./index.ts", + "./app": "./src/application.ts", + "./file": "./src/file.ts", + "./process": "./src/process.ts", + "./time": "./src/time.ts", + "./variable": "./src/variable.ts", + "./widgets": "./src/widgets.ts" + }, + "engines": { + "gjs": ">=1.79.0" + }, + "os": [ + "linux" + ], + "publishConfig": {}, "devDependencies": { "@ts-for-gir/cli": "^3.3.0", "@typescript-eslint/eslint-plugin": "^5.33.0", @@ -11,8 +38,6 @@ "typescript": "^5.1.0" }, "scripts": { - "build": "tsc", - "dev": "tsc --watch", "lint": "eslint .", "types": "ts-for-gir generate" } diff --git a/gjs/src/application.ts b/gjs/src/application.ts index 7147856..4a184e1 100644 --- a/gjs/src/application.ts +++ b/gjs/src/application.ts @@ -82,4 +82,4 @@ class AstalJS extends Astal.Application { } } -export const App = new AstalJS +export default new AstalJS diff --git a/gjs/src/astalify.ts b/gjs/src/astalify.ts index f198f68..6df57b4 100644 --- a/gjs/src/astalify.ts +++ b/gjs/src/astalify.ts @@ -105,7 +105,7 @@ function hook( return self } -function ctor(self: any, config: any = {}, children: any[] = []) { +function ctor(self: any, config: any = {}, children: any = []) { const { setup, ...props } = config props.visible ??= true diff --git a/gjs/src/file.ts b/gjs/src/file.ts index 0825e31..d15474b 100644 --- a/gjs/src/file.ts +++ b/gjs/src/file.ts @@ -36,5 +36,5 @@ export function monitorFile( path: string, callback: (file: string, event: Gio.FileMonitorEvent) => void, ): Gio.FileMonitor { - return Astal.monitor_file(path, callback) + return Astal.monitor_file(path, callback)! } diff --git a/gjs/src/widgets.ts b/gjs/src/widgets.ts index e363da0..29c0044 100644 --- a/gjs/src/widgets.ts +++ b/gjs/src/widgets.ts @@ -1,14 +1,16 @@ /* eslint-disable max-len */ import { Astal, Gtk } from "./imports.js" -import astalify, { type ConstructProps } from "./astalify.js" +import astalify, { type ConstructProps, type Widget } from "./astalify.js" export { astalify, ConstructProps } // Box +export type Box = Widget export const Box = astalify(Astal.Box) export type BoxProps = ConstructProps // Button +export type Button = Widget export const Button = astalify(Astal.Button) export type ButtonProps = ConstructProps // CenterBox +export type CenterBox = Widget export const CenterBox = astalify(Astal.CenterBox) export type CenterBoxProps = ConstructProps // TODO: CircularProgress // DrawingArea +export type DrawingArea = Widget export const DrawingArea = astalify(Gtk.DrawingArea) export type DrawingAreaProps = ConstructProps // Entry +export type Entry = Widget export const Entry = astalify(Gtk.Entry) export type EntryProps = ConstructProps // EventBox +export type EventBox = Widget export const EventBox = astalify(Astal.EventBox) export type EventBoxProps = ConstructProps export const Icon = astalify(Astal.Icon) export type IconProps = ConstructProps // Label +export type Label = Widget export const Label = astalify(Gtk.Label) export type LabelProps = ConstructProps // LevelBar +export type LevelBar = Widget export const LevelBar = astalify(Astal.LevelBar) export type LevelBarProps = ConstructProps // TODO: ListBox // Overlay +export type Overlay = Widget export const Overlay = astalify(Astal.Overlay) export type OverlayProps = ConstructProps // Revealer +export type Revealer = Widget export const Revealer = astalify(Gtk.Revealer) export type RevealerProps = ConstructProps // Scrollable +export type Scrollable = Widget export const Scrollable = astalify(Astal.Scrollable) export type ScrollableProps = ConstructProps // Slider +export type Slider = Widget export const Slider = astalify(Astal.Slider) export type SliderProps = ConstructProps // TODO: Stack // Switch +export type Switch = Widget export const Switch = astalify(Gtk.Switch) export type SwitchProps = ConstructProps // Window +export type Window = Widget export const Window = astalify(Astal.Window) export type WindowProps = ConstructProps diff --git a/gjs/tsconfig.json b/gjs/tsconfig.json index b5b6115..a259dd9 100644 --- a/gjs/tsconfig.json +++ b/gjs/tsconfig.json @@ -1,23 +1,23 @@ { "compilerOptions": { - "target": "ES2022", - "module": "ES2022", + "target": "ESNext", + "module": "ESNext", "lib": [ - "ES2022" + "ESNext" ], "outDir": "dist", + "declaration": true, "strict": true, - "moduleResolution": "node", - "baseUrl": ".", + "moduleResolution": "Bundler", "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "declaration": true, - "allowSyntheticDefaultImports": true + "checkJs": true, + "allowJs": true, + "jsx": "react-jsx", + "jsxImportSource": "./src/jsx" }, "include": [ - "./node_modules/@girs", "./src", "./index.ts", - "./sample.js" + "./node_modules/@girs" ] } -- cgit v1.2.3