├── .gitignore ├── screenshots ├── dark.png ├── light.png └── tan.png ├── themes └── cdr │ └── captivate │ ├── defaults │ ├── palette.tid │ ├── layout.tid │ ├── vanilla-themetweaks.tid │ ├── DefaultCaptivateTan.tid │ ├── DefaultCaptivateDark.tid │ └── DefaultCaptivateLight.tid │ ├── ui │ ├── SideBarDefault.tid │ ├── AdvancedSearch │ │ ├── Filter.tid │ │ ├── AdvancedSearch.tid │ │ ├── DefaultSearchResultList.tid │ │ └── System.tid │ ├── BottomBar.tid │ ├── FabButtons.tid │ ├── TopBarMenu.tid │ ├── TopBar.tid │ ├── PageLayout.tid │ ├── SideBar.tid │ └── TopBarSearch.tid │ ├── images │ ├── down-arrow.tid │ ├── close.tid │ └── edit.tid │ ├── settings.multids │ ├── plugin.info │ ├── palettes │ ├── DefaultMappings.multids │ ├── CaptivateTan.tid │ ├── CaptivateLight.tid │ └── CaptivateDark.tid │ ├── readme.tid │ ├── css │ ├── highlight-js-dark.tid │ ├── base-layout.tid │ └── base.tid │ └── tweaks │ ├── themetweaks.tid │ └── colors.tid ├── wiki ├── tiddlers │ ├── default-theme.tid │ ├── DefaultTiddlers.tid │ ├── config-home-btn.tid │ ├── $__SiteTitle.tid │ ├── $__SiteSubtitle.tid │ ├── colorschemes-black.tid │ ├── colorschemes-white.tid │ └── Intro.tid └── tiddlywiki.info ├── plugins └── cdr │ └── colorlab │ ├── plugin.info │ ├── demo │ ├── styles.css.tid │ └── lightness.tid │ ├── color-alpha.js │ ├── color-over.js │ ├── color-deviate.js │ ├── color-eval.js │ ├── color-mix.js │ ├── color-mute.js │ ├── color-autocontrast.js │ ├── color-lightness.js │ ├── contrastcolour.js │ ├── twutils.js │ ├── color-filters.js │ ├── action-wikifypalette.js │ └── lib │ ├── parse.js │ ├── color.js │ └── convert.js ├── .github └── workflows │ └── build.yml ├── package.json ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | **/output/ 2 | /node_modules/ -------------------------------------------------------------------------------- /screenshots/dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdruan/tw5-captivate/HEAD/screenshots/dark.png -------------------------------------------------------------------------------- /screenshots/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdruan/tw5-captivate/HEAD/screenshots/light.png -------------------------------------------------------------------------------- /screenshots/tan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cdruan/tw5-captivate/HEAD/screenshots/tan.png -------------------------------------------------------------------------------- /themes/cdr/captivate/defaults/palette.tid: -------------------------------------------------------------------------------- 1 | title: $:/palette 2 | 3 | $:/palettes/CaptivateLight -------------------------------------------------------------------------------- /themes/cdr/captivate/defaults/layout.tid: -------------------------------------------------------------------------------- 1 | title: $:/layout 2 | 3 | $:/themes/cdr/captivate/ui/PageLayout -------------------------------------------------------------------------------- /wiki/tiddlers/default-theme.tid: -------------------------------------------------------------------------------- 1 | title: $:/theme 2 | type: text/vnd.tiddlywiki 3 | 4 | $:/themes/cdr/captivate -------------------------------------------------------------------------------- /wiki/tiddlers/DefaultTiddlers.tid: -------------------------------------------------------------------------------- 1 | title: $:/DefaultTiddlers 2 | type: text/vnd.tiddlywiki 3 | 4 | [[Captivate Theme Demo]] 5 | -------------------------------------------------------------------------------- /wiki/tiddlers/config-home-btn.tid: -------------------------------------------------------------------------------- 1 | title: $:/config/PageControlButtons/Visibility/$:/core/ui/Buttons/home 2 | type: text/vnd.tiddlywiki 3 | 4 | show -------------------------------------------------------------------------------- /wiki/tiddlers/$__SiteTitle.tid: -------------------------------------------------------------------------------- 1 | created: 20220122124515594 2 | modified: 20220122124518366 3 | title: $:/SiteTitle 4 | type: text/vnd.tiddlywiki 5 | 6 | Captivate Theme -------------------------------------------------------------------------------- /wiki/tiddlers/$__SiteSubtitle.tid: -------------------------------------------------------------------------------- 1 | created: 20220122124527539 2 | modified: 20220122125941360 3 | title: $:/SiteSubtitle 4 | type: text/vnd.tiddlywiki 5 | 6 | gives your wiki a pop of color -------------------------------------------------------------------------------- /plugins/cdr/colorlab/plugin.info: -------------------------------------------------------------------------------- 1 | { 2 | "title": "$:/plugins/cdr/colorlab", 3 | "name": "Color Library", 4 | "description": "Color manipulation library", 5 | "author": "cdruan", 6 | "list": "", 7 | "version": "0.2.0" 8 | } -------------------------------------------------------------------------------- /wiki/tiddlers/colorschemes-black.tid: -------------------------------------------------------------------------------- 1 | title: $:/snippets/colorschemes/black 2 | type: application/x-tiddler-dictionary 3 | name: Black (testing) 4 | tags: $:/tags/ColorScheme 5 | 6 | color1: #000000 7 | color2: #000000 8 | color3: #000000 9 | -------------------------------------------------------------------------------- /wiki/tiddlers/colorschemes-white.tid: -------------------------------------------------------------------------------- 1 | title: $:/snippets/colorschemes/white 2 | type: application/x-tiddler-dictionary 3 | name: White (testing) 4 | tags: $:/tags/ColorScheme 5 | 6 | color1: #ffffff 7 | color2: #ffffff 8 | color3: #ffffff 9 | -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/SideBarDefault.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/ui/SideBar/default 2 | description: determines default sidebar setting (open or closed) 3 | 4 | [{$:/info/browser/screen/width}] [{$:/info/browser/screen/height}] +[minall[]compare:number:gt[1024]then[yes]else[no]] -------------------------------------------------------------------------------- /themes/cdr/captivate/defaults/vanilla-themetweaks.tid: -------------------------------------------------------------------------------- 1 | caption: {{$:/language/ThemeTweaks/ThemeTweaks}} 2 | title: $:/themes/tiddlywiki/vanilla/themetweaks 3 | type: text/vnd.tiddlywiki 4 | 5 | Overwritten by $:/themes/cdr/captivate so that the Vanilla theme tweaks do not appear in the control panel. -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/AdvancedSearch/Filter.tid: -------------------------------------------------------------------------------- 1 | title: $:/core/ui/AdvancedSearch/Filter 2 | tags: $:/tags/AdvancedSearch 3 | caption: {{$:/language/Search/Filter/Caption}} 4 | first-search-filter: [subfilter{$:/temp/advancedsearch}] 5 | 6 | <$transclude tiddler="$:/core" subtiddler="$:/core/ui/AdvancedSearch/Filter"/> -------------------------------------------------------------------------------- /themes/cdr/captivate/images/down-arrow.tid: -------------------------------------------------------------------------------- 1 | title: $:/core/images/down-arrow 2 | tags: $:/tags/Image 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /themes/cdr/captivate/settings.multids: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/ 2 | 3 | settings/accent-topbar: no 4 | settings/color-primary: #5778d8 5 | settings/color-secondary: #eecc66 6 | settings/color-link: #5778d8 7 | settings/palette-theme: light 8 | settings/text-on-dark: range(67,85) 9 | settings/text-on-light: range(10,48) 10 | settings/tiddlerwidth: 900px -------------------------------------------------------------------------------- /themes/cdr/captivate/images/close.tid: -------------------------------------------------------------------------------- 1 | title: $:/core/images/close-button 2 | tags: $:/tags/Image 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/demo/styles.css.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/cdr/colorlab/demo/styles.css 2 | tags: $:/tags/Stylesheet 3 | type: text/css 4 | 5 | .demo-colorbox{ 6 | display: inline-block; 7 | font-weight:500; 8 | text-align:center; 9 | width:190px; 10 | margin:10px 5px 0px; 11 | padding:15px 10px; 12 | } 13 | 14 | .demo-rangectrl { 15 | margin: 3px 10px 0px; 16 | width: 45%; 17 | } 18 | -------------------------------------------------------------------------------- /themes/cdr/captivate/plugin.info: -------------------------------------------------------------------------------- 1 | { 2 | "title": "$:/themes/cdr/captivate", 3 | "name": "Captivate", 4 | "author": "cdruan", 5 | "core-version": ">=5.2.0", 6 | "plugin-type": "theme", 7 | "description": "Switchable layouts with custom palettes", 8 | "dependents": ["$:/themes/tiddlywiki/vanilla","$:/plugins/cdr/colorlab"], 9 | "list": ["contents", "readme"], 10 | "version": "0.2.1" 11 | } -------------------------------------------------------------------------------- /themes/cdr/captivate/images/edit.tid: -------------------------------------------------------------------------------- 1 | title: $:/core/images/edit-button 2 | tags: $:/tags/Image 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/AdvancedSearch/AdvancedSearch.tid: -------------------------------------------------------------------------------- 1 | title: $:/AdvancedSearch 2 | icon: $:/core/images/advanced-search-button 3 | color: #bbb 4 | 5 | \whitespace trim 6 | 7 | <$eventcatcher selector="div.tc-advanced-search" $click="""<$action-deletetiddler $tiddler="$:/temp/advancedsearch/input/topbar"/>""" stopPropagation="never" tag="div"> 8 | <$transclude tiddler="$:/core" subtiddler="$:/AdvancedSearch"/> 9 | 10 | -------------------------------------------------------------------------------- /wiki/tiddlers/Intro.tid: -------------------------------------------------------------------------------- 1 | title: Captivate Theme Demo 2 | created: 20210701212256020 3 | modified: 20220122122702255 4 | type: text/vnd.tiddlywiki 5 | tags: introduction 6 | 7 | !! Design Your Own Color Palette 8 | 9 | {{$:/themes/cdr/captivate/tweaks/colors}} 10 | 11 | --- 12 | 13 | * For details about the theme, see [[README|$:/themes/cdr/captivate/readme]] 14 | 15 | * Press <> to switch between page layouts. -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/BottomBar.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/ui/BottomBar 2 | tags: $:/tags/PageTemplate 3 | list-before: $:/themes/cdr/captivate/ui/SideBar 4 | 5 | \whitespace trim 6 | 7 | <$list filter="[{$:/layout}match[$:/themes/cdr/captivate/ui/PageLayout]]" variable="ignore"> 8 | 9 |
10 | 11 | 12 | 13 | <$transclude tiddler="$:/core/ui/SideBarSegments/page-controls" mode="inline" /> 14 | 15 |
16 | 17 | -------------------------------------------------------------------------------- /themes/cdr/captivate/palettes/DefaultMappings.multids: -------------------------------------------------------------------------------- 1 | title: $:/config/DefaultColourMappings/ 2 | 3 | secondary-button-background: {{{ [colour[primary]lightness[90]] }}} 4 | secondary-button-background-hover: {{{ [colour[primary]lightness[85]] }}} 5 | secondary-button-foreground: {{{ [colour[primary]lightness[35]] }}} 6 | secondary-button-border: {{{ [colour[primary]lightness[60]] }}} 7 | fab-background: {{{ [colour[page-background]deviate[]] }}} 8 | fab-background-hover: {{{ [colour[primary]lightness[80]] }}} 9 | fab-foreground: {{{ [colour[primary]lightness[68]] }}} 10 | sidebar-background: {{{ [colour[page-background]] }}} 11 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Deploy 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | workflow_dispatch: 8 | 9 | jobs: 10 | deploy: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v2 14 | with: 15 | persist-credentials: false 16 | - uses: actions/setup-node@v2-beta 17 | with: 18 | node-version: '16' 19 | 20 | - name: Install Dependency 21 | run: npm ci 22 | 23 | - name: Build 24 | run: | 25 | npm run build 26 | 27 | - name: Deploy 28 | uses: peaceiris/actions-gh-pages@v3 29 | with: 30 | github_token: ${{ secrets.GITHUB_TOKEN }} 31 | publish_branch: gh-pages 32 | publish_dir: wiki/output 33 | keep_files: true -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tw5-captivate", 3 | "version": "1.0.0", 4 | "description": "TiddlyWiki theme with easy color customization", 5 | "dependencies": { 6 | "tiddlywiki": "^5.1.23" 7 | }, 8 | "scripts": { 9 | "build": "TIDDLYWIKI_PLUGIN_PATH=plugins TIDDLYWIKI_THEME_PATH=themes node ./node_modules/tiddlywiki/tiddlywiki.js wiki --build index", 10 | "start": "TIDDLYWIKI_PLUGIN_PATH=plugins TIDDLYWIKI_THEME_PATH=themes node ./node_modules/tiddlywiki/tiddlywiki.js wiki --listen" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/cdruan/tw5-captivate.git" 15 | }, 16 | "keywords": [ 17 | "TW5", 18 | "TW5-plugins", 19 | "tiddlywiki" 20 | ], 21 | "author": "cdruan", 22 | "license": "MIT", 23 | "bugs": { 24 | "url": "https://github.com/cdruan/tw5-captivate/issues" 25 | }, 26 | "homepage": "https://github.com/cdruan/tw5-captivate#readme" 27 | } 28 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/color-alpha.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/color-alpha.js 3 | type: application/javascript 4 | module-type: macro 5 | 6 | Manipulate alpha component of a color or return given color's alpha value. 7 | \*/ 8 | 9 | (function(){ 10 | 11 | /* jslint node: true, browser: true */ 12 | /* global $tw: false */ 13 | "use strict"; 14 | 15 | exports.name = "color-alpha"; 16 | 17 | exports.params = [ 18 | {name: "color"}, 19 | {name: "value"} 20 | ]; 21 | 22 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 23 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 24 | 25 | exports.run = function(color,value) { 26 | color = new Color(utils.wikifyText(color,this)); 27 | 28 | if (value === void(0) || value.trim() === "") { 29 | return color.alpha.toString(); 30 | } 31 | 32 | var num = isNaN(value) ? 0 : parseFloat(value); 33 | 34 | color.alpha = num; 35 | return color.toString(); 36 | }; 37 | 38 | })(); 39 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/color-over.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/color-over.js 3 | type: application/javascript 4 | module-type: macro 5 | 6 | Alpha composite with source over operator 7 | \*/ 8 | 9 | (function(){ 10 | /* jslint node: true, browser: true */ 11 | /* global $tw: false */ 12 | "use strict"; 13 | 14 | exports.name = "color-over"; 15 | 16 | exports.params = [ 17 | {name: "top"}, 18 | {name: "bottom"}, 19 | ]; 20 | 21 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 22 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 23 | 24 | /** 25 | * Computes weighted average of two colors in LCH color space 26 | * @param {Color} top top color 27 | * @param {Color} bottom bottom color 28 | * @returns {Color} returns top over bottom composite result 29 | */ 30 | exports.run = function(top,bottom) { 31 | top = new Color(utils.wikifyText(top,this)); 32 | bottom = new Color(utils.wikifyText(bottom,this)); 33 | 34 | return top.over(bottom).toString('rgb'); 35 | }; 36 | 37 | })(); 38 | -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/FabButtons.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/ui/FabButtons 2 | tags: $:/tags/PageTemplate 3 | list-before: $:/core/ui/PageTemplate/story 4 | 5 | \whitespace trim 6 | \define config-title() 7 | $:/config/PageControlButtons/Visibility/$(listItem)$ 8 | \end 9 | 10 | <$list filter="[{$:/layout}match[$:/themes/cdr/captivate/ui/PageLayout]]" variable="ignore"> 11 | 12 |
13 | 14 |
15 | 16 | <$list filter="[all[shadows+tiddlers]tag[$:/tags/PageControls]!has[draft.of]]" variable="listItem"> 17 | 18 | <$set name="hidden" value=<>> 19 | 20 | <$list filter="[!text[hide]]" storyview="pop" variable="ignore"> 21 | 22 | <$set name="tv-config-toolbar-class" value="cv-fab-item"> 23 | 24 |
25 | 26 | <$transclude tiddler=<> mode="inline"/> 27 | 28 |
29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | 40 |
41 | 42 | -------------------------------------------------------------------------------- /wiki/tiddlywiki.info: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Basic client-server edition", 3 | "plugins": [ 4 | "cdr/colorlab", 5 | "tiddlywiki/tiddlyweb", 6 | "tiddlywiki/filesystem", 7 | "tiddlywiki/highlight" 8 | ], 9 | "themes": [ 10 | "cdr/captivate", 11 | "tiddlywiki/vanilla", 12 | "tiddlywiki/snowwhite" 13 | ], 14 | "build": { 15 | "index": [ 16 | "--rendertiddler", "$:/plugins/tiddlywiki/tiddlyweb/save/offline", "index.html", "text/plain" 17 | ], 18 | "static": [ 19 | "--rendertiddler", "$:/core/templates/static.template.html", "static.html", "text/plain", 20 | "--rendertiddler", "$:/core/templates/alltiddlers.template.html", "alltiddlers.html", "text/plain", 21 | "--rendertiddlers", "[!is[system]]", "$:/core/templates/static.tiddler.html", "static", "text/plain", 22 | "--rendertiddler", "$:/core/templates/static.template.css", "static/static.css", "text/plain" 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Captivate 2 | 3 | This is a TiddlyWiki theme that offers a left sidebar layout and easy color customization. 4 | 5 | light theme 6 | dark theme 7 | tan theme 8 | 9 | ## Features 10 | 11 | * Adds a pop of color to your wiki with just a few clicks. Pick any three colors and receive these variations of your color scheme: light, dark, and tan. 12 | * Incorporates TiddlyWiki's layout switching mechanism. At a minimum, you can switch between the Captivate layout and the default TiddlyWiki layout by pressing Ctrl-Shift-L. 13 | * Supports display-p3 color values and gracefully falls back to sRGB for browsers that do not support this color space. 14 | 15 | ## Demo 16 | 17 | For a demonstration, visit [https://cdruan.github.io/tw5-captivate](https://cdruan.github.io/tw5-captivate) 18 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/color-deviate.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/color-deviate.js 3 | type: application/javascript 4 | module-type: macro 5 | 6 | Adjust the color a bit. If the color is on the dark side, make it slightly 7 | lighter; and make a light color slightly darker. 8 | \*/ 9 | 10 | (function(){ 11 | 12 | /* jslint node: true, browser: true */ 13 | /* global $tw: false */ 14 | "use strict"; 15 | 16 | exports.name = "color-deviate"; 17 | 18 | exports.params = [ 19 | {name: "color"}, 20 | ]; 21 | 22 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 23 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 24 | 25 | exports.run = function(color,value) { 26 | color = new Color(utils.wikifyText(color,this)); 27 | 28 | var lightness = color.lightness; 29 | var adjust; 30 | 31 | var newval; 32 | if(lightness < 40) { 33 | newval = 0.085 * Math.pow(lightness,1.45) + 28; 34 | } else { 35 | newval = lightness - Math.pow(Math.max(100-lightness,11),0.79) * 0.4; 36 | } 37 | color.lightness = newval; 38 | return color.toString(); 39 | }; 40 | 41 | })(); -------------------------------------------------------------------------------- /plugins/cdr/colorlab/color-eval.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/color-eval.js 3 | type: application/javascript 4 | module-type: macro 5 | 6 | Returns a color string that is supported by the browser. Can be used to 7 | "downgrade" a p3 color string on browsers that don't support p3 color space. 8 | \*/ 9 | 10 | (function(){ 11 | 12 | /* jslint node: true, browser: true */ 13 | /* global $tw: false */ 14 | "use strict"; 15 | 16 | exports.name = "color-eval"; 17 | 18 | exports.params = [ 19 | {name: "color"}, 20 | ]; 21 | 22 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 23 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 24 | 25 | exports.run = function(color) { 26 | var cssColor = utils.wikifyText(color,this); 27 | color = Color.parse(cssColor); 28 | if (! color) { 29 | return ""; 30 | } 31 | 32 | if (color.space && color.space !== "rgb" && $tw.browser) { 33 | if (window.matchMedia("(color-gamut: p3)").matches) { 34 | return (new Color(color)).toString("p3"); 35 | } 36 | return (new Color(color)).toString("rgb"); 37 | } 38 | return cssColor; 39 | }; 40 | 41 | })(); -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 cdruan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /themes/cdr/captivate/readme.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/readme 2 | created: 20210701212256020 3 | modified: 20220122074304455 4 | 5 | This theme aims to provide another clean and functional layout for <$text text="TiddlyWiki"/>. 6 | 7 | !! Features 8 | 9 | Captivate allows you to: 10 | 11 | * Personalize the colors of your wiki with just a few clicks. 12 | * Switch between Captivate and the default <$text text="TiddlyWiki"/> layout. 13 | * Incorporate [[display-p3|https://webkit.org/blog/10042/wide-gamut-color-in-css-with-display-p3/]] color. The theme will gracefully fall back to sRGB when necessary. 14 | 15 | !! Installation 16 | 17 | To add this theme to your own <$text text="TiddlyWiki"/> 18 | 19 | # Drag the following links to your wiki: 20 | #* [[$:/themes/cdr/captivate]] 21 | #* [[$:/plugins/cdr/colorlab]] 22 | # Save and reload 23 | # Select the ''Captivate'' theme in ''[[$:/ControlPanel]] > Appearance > Theme'' 24 | 25 | !! Usage 26 | 27 | * To generate personal color palettes, go to ''[[$:/ControlPanel]] > Appearance > Theme Tweaks'' 28 | * To switch the page layout, use the keyboard shortcut <> -------------------------------------------------------------------------------- /plugins/cdr/colorlab/color-mix.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/color-mix.js 3 | type: application/javascript 4 | module-type: macro 5 | 6 | Mix two colors. 7 | \*/ 8 | 9 | (function(){ 10 | /* jslint node: true, browser: true */ 11 | /* global $tw: false */ 12 | "use strict"; 13 | 14 | exports.name = "color-mix"; 15 | 16 | exports.params = [ 17 | {name: "color1"}, 18 | {name: "color2"}, 19 | {name: "weight",default: 0.5} 20 | ]; 21 | 22 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 23 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 24 | 25 | /** 26 | * Computes weighted average of two colors in LCH color space 27 | * @param {Color} color1 28 | * @param {Color} color2 29 | * @param {number} [weight=0.5] weight [0..1] given to color2 in blend 30 | * @returns {Color} The blended color 31 | */ 32 | exports.run = function(color1,color2,weight) { 33 | color1 = new Color(utils.wikifyText(color1,this)); 34 | color2 = new Color(utils.wikifyText(color2,this)); 35 | 36 | if (weight === void(0) || isNaN(weight)) { 37 | weight = 0.5; 38 | } else { 39 | weight = isNaN(weight) ? 0.5 : parseFloat(weight); 40 | } 41 | 42 | return color1.mix(color2,weight).toString(); 43 | }; 44 | 45 | })(); 46 | -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/TopBarMenu.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/ui/TopBar/Menu 2 | 3 | \whitespace trim 4 | 5 | \define sidebarOpen() [[$:/state/sidebar]get[text]] ~[subfilter{$:/themes/cdr/captivate/ui/SideBar/default}] +[match[yes]] 6 | 7 | \define sidebarClosed() [[$:/state/sidebar]get[text]] ~[subfilter{$:/themes/cdr/captivate/ui/SideBar/default}] +[match[no]] 8 | 9 | 10 | <$list filter=<> variable="ignore"> 11 | 12 | <$button set="$:/state/sidebar" setTo="no" tooltip={{$:/language/Buttons/HideSideBar/Hint}} aria-label={{$:/language/Buttons/HideSideBar/Caption}} class="tc-btn-invisible tc-hide-sidebar-btn cv-topbar-btn"> 13 | 14 | <$transclude tiddler="$:/core/images/menu-button" mode="inline"/> 15 | 16 | 17 | 18 | 19 | 20 | <$list filter=<> variable="ignore"> 21 | 22 | <$button set="$:/state/sidebar" setTo="yes" tooltip={{$:/language/Buttons/ShowSideBar/Hint}} aria-label={{$:/language/Buttons/ShowSideBar/Caption}} class="tc-btn-invisible tc-show-sidebar-btn cv-topbar-btn"> 23 | 24 | <$transclude tiddler="$:/core/images/menu-button" mode="inline"/> 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/AdvancedSearch/DefaultSearchResultList.tid: -------------------------------------------------------------------------------- 1 | title: $:/core/ui/DefaultSearchResultList 2 | tags: $:/tags/SearchResults 3 | caption: {{$:/language/Search/DefaultResults/Caption}} 4 | first-search-filter: [!is[system]search:titlesort[title]limit[250]] 5 | second-search-filter: [!is[system]searchsort[title]limit[250]] 6 | 7 | \define searchResultList() 8 | \whitespace trim 9 |
10 | 11 | //{{$:/language/Search/Matches/Title}}// 12 | 13 | <$list filter="[minlength[1]]" variable="ignore"> 14 | <$list filter={{{ [get[first-search-filter]] }}}> 15 | addsuffix[-primaryList]] -[get[text]] +[then[]else[tc-list-item-selected]] }}}> 16 | <$transclude tiddler="$:/core/ui/ListItemTemplate"/> 17 | 18 | 19 | 20 | 21 | //{{$:/language/Search/Matches/All}}// 22 | 23 | <$list filter="[minlength[1]]" variable="ignore"> 24 | <$list filter={{{ [get[second-search-filter]] }}}> 25 | addsuffix[-secondaryList]] -[get[text]] +[then[]else[tc-list-item-selected]] }}}> 26 | <$transclude tiddler="$:/core/ui/ListItemTemplate"/> 27 | 28 | 29 | 30 | 31 |
32 | \end 33 | <> 34 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/color-mute.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/color-mute.js 3 | type: application/javascript 4 | module-type: macro 5 | 6 | Adjust the saturation/chroma of the color. 7 | \*/ 8 | 9 | (function(){ 10 | 11 | /* jslint node: true, browser: true */ 12 | /* global $tw: false */ 13 | "use strict"; 14 | 15 | exports.name = "color-mute"; 16 | 17 | exports.params = [ 18 | {name: "color"}, 19 | ]; 20 | 21 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 22 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 23 | 24 | /* 25 | This is an ad hoc function to tone down a color. Avoid pale color to be too 26 | gray. Make dark colors paler, i.e. bring up their lightness level. 27 | */ 28 | exports.run = function(color) { 29 | // avoid wide-gamut color space by bringing color down to sRGB 30 | color = (new Color(utils.wikifyText(color,this))).to("rgb"); 31 | var lch = color.lch; 32 | var percent = 30; // chroma reduction 33 | var lightness = lch[0]; 34 | 35 | if (lightness >= 70) { 36 | var b=200; // higher the less decrease 37 | 38 | // lower the lightness slightly as it approaches 100 39 | lightness = b * Math.atan((lightness - 30)/b)+30; 40 | 41 | // less chroma reduction as lightness goes up 42 | percent = 22 * (1 + (87 - lightness)/87); 43 | } else if (lightness < 30) { 44 | lightness = 0.3 * lightness + 21; 45 | } 46 | 47 | lch[0] = lightness; 48 | lch[1] -= lch[1] * percent/100; 49 | color.lch = lch; 50 | return color.toString('rgb'); 51 | }; 52 | })(); 53 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/color-autocontrast.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/color-autocontrast.js 3 | type: application/javascript 4 | module-type: macro 5 | 6 | Generates a contrasting color. If the given color is dark enough, 7 | returns white as the contrast color; otherwise, returns the darker version 8 | of the input color. Alpha is ignored. 9 | 10 | When given the optional "against" parameter, generate constrasting color against 11 | this parameter. 12 | \*/ 13 | 14 | (function(){ 15 | 16 | /* jslint node: true, browser: true */ 17 | /* global $tw: false */ 18 | "use strict"; 19 | 20 | exports.name = "color-autocontrast"; 21 | 22 | exports.params = [ 23 | {name: "color"}, 24 | {name: "against"} 25 | ]; 26 | 27 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 28 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 29 | 30 | exports.run = function(color,against) { 31 | color = new Color(utils.wikifyText(color,this)); 32 | 33 | var colorLight = color.lightness; 34 | 35 | if (against === "") { 36 | // return color based color's lightness 37 | if(colorLight < utils.MaxContrastWhite) { 38 | return "#ffffff"; 39 | } 40 | 41 | color.lightness = 20; 42 | return color.toString('rgb'); 43 | } else { 44 | against = new Color(utils.wikifyText(against,this)); 45 | var againstLight = against.lightness; 46 | 47 | if (Math.abs(colorLight - againstLight) < 35) { 48 | colorLight = againstLight + (againstLight < 50 ? 35 : -35); 49 | } 50 | color.lightness = colorLight; 51 | return color.toString('rgb'); 52 | } 53 | }; 54 | 55 | })(); 56 | -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/TopBar.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/ui/TopBar 2 | tags: $:/tags/PageTemplate 3 | list-before: $:/themes/cdr/captivate/ui/SideBar 4 | 5 | \whitespace trim 6 | 7 | <$list filter="[{$:/layout}match[$:/themes/cdr/captivate/ui/PageLayout]]" variable="ignore"> 8 | 9 |
10 | 11 | 14 | 15 | {{$:/themes/cdr/captivate/ui/TopBar/Menu}} 16 | 17 |
18 | 19 |
20 | 21 | <$view tiddler="$:/SiteTitle" format="plainwikified"/> 22 | 23 |
24 | 25 | 26 | 27 | 31 | 32 | <$transclude tiddler="$:/themes/cdr/captivate/ui/TopBar/Search" mode="inline" /> 33 | 34 | 40 | 41 | 42 | 43 | 46 | 47 |
48 | 49 |
50 | 51 | 52 | -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/PageLayout.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/ui/PageLayout 2 | tags: $:/tags/Layout 3 | name: Captivate 4 | description: left sidebar layout 5 | 6 | \whitespace trim 7 | \define containerClasses() 8 | tc-page-container tc-page-view-$(storyviewTitle)$ tc-language-$(languageTitle)$ 9 | \end 10 | \import [[$:/core/ui/PageMacros]] [all[shadows+tiddlers]tag[$:/tags/Macro]!has[draft.of]] 11 | 12 | <$vars 13 | tv-config-toolbar-icons={{$:/config/Toolbar/Icons}} 14 | tv-config-toolbar-text={{$:/config/Toolbar/Text}} 15 | tv-config-toolbar-class={{$:/config/Toolbar/ButtonClass}} 16 | tv-enable-drag-and-drop={{$:/config/DragAndDrop/Enable}} 17 | tv-show-missing-links={{$:/config/MissingLinks}} 18 | storyviewTitle={{$:/view}} 19 | languageTitle={{{ [{$:/language}get[name]] }}}> 20 | 21 |
>> 22 | 23 | <$navigator story="$:/StoryList" history="$:/HistoryList" openLinkFromInsideRiver={{$:/config/Navigation/openLinkFromInsideRiver}} openLinkFromOutsideRiver={{$:/config/Navigation/openLinkFromOutsideRiver}} relinkOnRename={{$:/config/RelinkOnRename}}> 24 | 25 | <$dropzone enable=<>> 26 | 27 | <$list filter="[all[shadows+tiddlers]tag[$:/tags/PageTemplate]!has[draft.of]] -[[$:/core/ui/PageTemplate/sidebar]] -[[$:/core/ui/PageTemplate/topleftbar]] -[[$:/core/ui/PageTemplate/toprightbar]]" variable="listItem"> 28 | 29 | 30 | 31 | <$transclude tiddler=<>/> 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 |
40 | 41 | 42 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/color-lightness.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/color-lightness.js 3 | type: application/javascript 4 | module-type: macro 5 | 6 | Manipulate lightness component of a color (in LCH space) or return given 7 | color's lightness value. 8 | \*/ 9 | 10 | (function(){ 11 | 12 | /* jslint node: true, browser: true */ 13 | /* global $tw: false */ 14 | "use strict"; 15 | 16 | exports.name = "color-lightness"; 17 | 18 | exports.params = [ 19 | {name: "color"}, 20 | {name: "value"} 21 | ]; 22 | 23 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 24 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 25 | 26 | exports.run = function(color,value) { 27 | color = new Color(utils.wikifyText(color,this)); 28 | 29 | if (value === void(0) || value.trim() === "") { 30 | return color.lightness.toString(); 31 | } 32 | 33 | var num, lightness = color.lightness; 34 | 35 | if (!isNaN(value)) { 36 | num = parseFloat(value); 37 | if(value[0] === "+" || value[0] === "-") { 38 | num += lightness; 39 | num = Math.min(Math.max(0,num),100); 40 | } 41 | } else { 42 | var re = /^\s*(min|max|range)\(([^)]+)\)\s*$/; 43 | var m = value.match(re); 44 | 45 | if (m) { 46 | switch(m[1]) { 47 | case "min": 48 | num = parseFloat(m[2]); 49 | num = Math.min(Math.max(num,lightness),100); 50 | break; 51 | case "max": 52 | num = parseFloat(m[2]); 53 | num = Math.max(Math.min(num,lightness),0); 54 | break; 55 | case "range": 56 | var args = m[2].split(','); 57 | args[0] = parseFloat(args[0]) || 0; 58 | args[1] = parseFloat(args[1]) || 0; 59 | num = Math.min(Math.max(lightness,args[0]),args[1]); 60 | break; 61 | } 62 | } else { 63 | num = 0; 64 | } 65 | } 66 | 67 | color.lightness = num; 68 | return color.toString(); 69 | }; 70 | 71 | })(); 72 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/contrastcolour.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/core/modules/macros/contrastcolour.js 3 | type: application/javascript 4 | module-type: macro 5 | 6 | Redefine contrastcolour. Wikify the arguments first and slightly preferrs 7 | lighter contrast to the dark one. 8 | \*/ 9 | 10 | (function(){ 11 | /*jslint node: true, browser: true */ 12 | /*global $tw: false */ 13 | "use strict"; 14 | 15 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 16 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 17 | 18 | exports.name = "contrastcolour"; 19 | 20 | exports.params = [ 21 | {name: "target"}, 22 | {name: "fallbackTarget"}, 23 | {name: "colourA"}, 24 | {name: "colourB"} 25 | ]; 26 | 27 | exports.run = function(target,fallbackTarget,colourA,colourB) { 28 | var colTarget = new Color(utils.wikifyText(target,this) || utils.wikifyText(fallbackTarget,this)); 29 | 30 | var colA = new Color(utils.wikifyText(colourA,this)); 31 | var colB = new Color(utils.wikifyText(colourB,this)); 32 | 33 | if (colTarget.alpha === 0) { 34 | return colA.toString(); 35 | } 36 | 37 | var contrastA = colTarget.contrast(colA), 38 | contrastB = colTarget.contrast(colB); 39 | 40 | var lightnessTarget = colTarget.lightness; 41 | var minContrast = 3.1; 42 | 43 | // if target is dark enough, prefer light contrast, even if contrast ratio is insufficient 44 | if (lightnessTarget <= utils.MaxContrastWhite) { 45 | var lightnessA = colA.lightness, 46 | lightnessB = colB.lightness; 47 | 48 | if (lightnessA >= lightnessB) { 49 | return (contrastA >= minContrast ? colA.toString() : "#ffffff"); 50 | } 51 | return (contrastB >= minContrast ? colB.toString() : "#ffffff"); 52 | } 53 | 54 | if (contrastA < minContrast && contrastB < minContrast) { 55 | return "#000000"; 56 | } 57 | return (contrastA >= contrastB ? colA.toString() : colB.toString()); 58 | }; 59 | 60 | })(); 61 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/twutils.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/twutils.js 3 | type: application/javascript 4 | module-type: library 5 | 6 | Utility functions. 7 | 8 | \*/ 9 | (function() { 10 | 11 | /*jslint node: true, browser: true */ 12 | /*global $tw: true */ 13 | "use strict"; 14 | 15 | /** 16 | * UI components: background color <= this lightness can 17 | * be paired with white text with enough contrast even 18 | * if the contrast ratio is less than recommended AA 19 | */ 20 | exports.MaxContrastWhite = 75; 21 | 22 | exports.wikifyText = function (t, parentWidget) { 23 | var parser = $tw.wiki.parseText("text/vnd.tiddlywiki",t,{ parseAsInline: true }); 24 | var widgetNode = $tw.wiki.makeWidget(parser,{ 25 | document: $tw.fakeDocument, 26 | parentWidget: parentWidget 27 | }); 28 | var container = $tw.fakeDocument.createElement("div"); 29 | widgetNode.render(container,null); 30 | return container.textContent; 31 | } 32 | 33 | var _parseCSSColor = $tw.utils.parseCSSColor; 34 | 35 | // process hex codes separately since TW's parser doesn't accept alpha channel 36 | // in hex codes 37 | $tw.utils.parseCSSColor = function(str) { 38 | // #RGB[A] and #RRGGBB[AA] syntax. 39 | if (str[0] === '#') { 40 | if (isNaN("0x"+str.slice(1))) { 41 | return null; 42 | } 43 | if (str.length === 4 || str.length === 5) { 44 | var iv = parseInt((str+"f").slice(1,5), 16); 45 | return [((iv & 0xf000) >> 8) | ((iv & 0xf000) >> 12), 46 | (iv & 0xf00) >> 4| ((iv & 0xf00) >> 8), 47 | (iv & 0xf0) | ((iv & 0xf0) >> 4), 48 | ((iv & 0xf) | ((iv & 0xf) << 4)) / 255]; 49 | } else if (str.length === 7 || str.length === 9) { 50 | var iv = parseInt((str+"ff").slice(1,9), 16); 51 | return [(iv & 0xff000000) >>> 24, 52 | (iv & 0xff0000) >> 16, 53 | (iv & 0xff00) >> 8, 54 | (iv & 0xff) / 255]; 55 | } 56 | 57 | return null; 58 | } 59 | 60 | var rgb = null; 61 | try { 62 | rgb = _parseCSSColor(str); 63 | } finally { 64 | return rgb; 65 | } 66 | } 67 | 68 | })(); 69 | -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/SideBar.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/ui/SideBar 2 | tags: $:/tags/PageTemplate 3 | list-before: $:/core/ui/PageTemplate/story 4 | 5 | \whitespace trim 6 | 7 | \define sidebarDefaultFilter() [{$:/info/browser/screen/width}compare:number:gt{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}then[yes]else[no]] 8 | 9 | \define sidebarDefaultState() {{{[{$:/info/browser/screen/width}compare:number:gt{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}then[yes]else[no]]}}} 10 | 11 | \define sidebarTabs() <$macrocall $name="tabs" tabsList="[all[shadows+tiddlers]tag[$:/tags/SideBar]!has[draft.of]]" default={{$:/config/DefaultSidebarTab}} state="$:/state/tab/sidebar" class="tc-sidebar-tabs-main"/> 12 | 13 | <$list filter="[{$:/layout}match[$:/themes/cdr/captivate/ui/PageLayout]]" variable="ignore"> 14 | 15 | <$set name=defaultState filter=<> > 16 | 17 | <$reveal state="$:/state/sidebar" type="nomatch" text="no" retain="yes" animate="yes" tag="div" class="cv-sidebar" default={{{ [subfilter{$:/themes/cdr/captivate/ui/SideBar/default}] }}} retain="yes" animate="yes"> 18 | 19 |
20 | 21 | {{$:/themes/cdr/captivate/ui/TopBar/Menu}} 22 | 23 | 24 | 25 | <$view tiddler="$:/SiteTitle" format="plainwikified"/> 26 | 27 | 28 | 29 |
30 | 31 |
32 | 33 | 34 | 38 | <$list filter="[subfilter{$:/themes/cdr/captivate/ui/SideBar/default}match[no]]" 39 | emptyMessage=<>> 40 | 41 | <$linkcatcher actions="""<$action-setfield $tiddler="$:/state/sidebar" $value="no"/><$action-navigate $to=<>/>"""> 42 | 43 | <> 44 | 45 | 46 | 47 | 48 | 49 |
50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/color-filters.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/color-filters.js 3 | type: application/javascript 4 | module-type: filteroperator 5 | 6 | Filter operators for colors. 7 | \*/ 8 | (function(){ 9 | 10 | /*jslint node: true, browser: true */ 11 | /*global $tw: false */ 12 | "use strict"; 13 | 14 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 15 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 16 | 17 | /* 18 | * input: ignored 19 | * parameter: index name in palette, e.g. page-background 20 | * output: color value, currently an rgb[a] value 21 | */ 22 | exports.colour = function(source,operator,options) { 23 | if (operator.operand.trim().length === 0) { 24 | return []; 25 | } 26 | 27 | var text = "<>", 28 | color = utils.wikifyText(text,options.widget); 29 | if (color !== "") { 30 | return [color]; 31 | } 32 | 33 | return []; 34 | }; 35 | 36 | exports.lightness = makeColorBinaryOperator("color-lightness"); 37 | 38 | exports.alpha = makeColorBinaryOperator("color-alpha"); 39 | 40 | exports.mute = makeColorBinaryOperator("color-mute"); 41 | 42 | /* 43 | Mix input with the operand with optional second operand specifying the 44 | weighting for the operand (default=0.5). 45 | */ 46 | exports.mix = function(source,operator,options) { 47 | var result = [], 48 | macro = $tw.macros["color-mix"]; 49 | //colorStr = utils.wikifyText(operator.operands[0].trim(),options.widget); 50 | 51 | source(function(tiddler,title) { 52 | result.push(macro.run.call(options.widget,title,operator.operand.trim(),operator.operands[1])); 53 | }); 54 | return result; 55 | }; 56 | 57 | exports.over = makeColorBinaryOperator("color-over"); 58 | 59 | exports.autocontrast = makeColorBinaryOperator("color-autocontrast"); 60 | 61 | /* 62 | Mix input with the operand with optional second operand specifying the 63 | weighting for the operand (default=0.5). 64 | */ 65 | exports.deviate = makeColorBinaryOperator("color-deviate"); 66 | 67 | function makeColorBinaryOperator(macroName) { 68 | return function(source,operator,options) { 69 | options = options || {widget: $tw.rootWidget}; 70 | var result = []; 71 | var macro = $tw.macros[macroName]; 72 | 73 | source(function(tiddler,title) { 74 | result.push(macro.run.call(options.widget,title,operator.operand.trim())); 75 | }); 76 | return result; 77 | }; 78 | } 79 | })(); -------------------------------------------------------------------------------- /plugins/cdr/colorlab/demo/lightness.tid: -------------------------------------------------------------------------------- 1 | title: $:/plugins/cdr/colorlab/demo/lightness 2 | type: text/vnd.tiddlywiki 3 | samples: #098cff #cddc39 #511ab2 #d3effd 4 | 5 | \define tempTiddler() $:/temp/demo/lch 6 | 7 | \define colorboxStyle() 8 | background-color:<$macrocall $name="color-eval" color="$(color)$" />; 9 | border-color:$(color)$; 10 | color:<$macrocall $name="color-autocontrast" color="$(color)$" />; 11 | font-size:0.95em; 12 | width: 220px; 13 | \end 14 | 15 | \define colortextStyle() 16 | color:$(color)$; 17 | text-align: center; 18 | font-weight: 400; 19 | \end 20 | 21 | \define showResult() 22 | <$wikify name=color text="""<$macrocall $name="color-lightness" color={{{[get[result]] ~[[#000000]]}}} value={{{[get[text]] ~[[0]]}}}/>"""> 23 | <$wikify name=boxstyle text=<> > 24 | > > 25 | <$text text=<> /> 26 | > > sample text 27 | 28 | 29 | \end 30 | 31 |
32 | Lightness: 33 | <$range class="demo-rangectrl" tiddler=<> min="0" max="100" default="0" increment="1"/> 34 | <$text text={{{[get[text]fixed[2]]}}}/> 35 |
36 | <> 37 | 38 |

Enter a color and click on the ''Reset'' button to see the color's lightness value:

39 | <$edit-text tiddler=<> field="initial" placeholder="css color string" default=""/>  40 | <$wikify name=initialLight text="""<$macrocall $name="color-lightness" color={{{[get[initial]]}}} />"""> 41 | <$button> 42 | <$action-setfield $tiddler=<> text=<> result={{{ [get[initial]] }}} />Reset 43 | 44 | 45 | 46 | !! Sample Colors: 47 | 48 | Click on a color to see its lightness value. 49 | 50 |
51 | <$list filter="[list[!!samples]]" variable="color"> 52 |
>> 53 | <$wikify name=boxstyle text=<> > 54 | <$button class="demo-colorbox" style=<> > 55 | <$text text=<> /> 56 | <$wikify name=initialLight text="""<$macrocall $name="color-lightness" color=<> />"""> 57 | <$action-setfield $tiddler=<> text=<> result=<> initial=<> /> 58 | 59 | 60 |
61 | Hello World 62 |
63 | 64 | 65 |
66 | 67 | -------------------------------------------------------------------------------- /themes/cdr/captivate/css/highlight-js-dark.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/css/highlight-js-dark 2 | tags: $:/tags/Stylesheet 3 | list-after: $:/plugins/tiddlywiki/highlight/styles 4 | 5 | <$reveal stateTitle={{$:/palette}} stateField="color-scheme" type="match" text="dark" default="light"> 6 | .hljs { 7 | display: block; 8 | overflow-x: auto; 9 | padding: 0.5em; 10 | background: <>; 11 | color: <>; 12 | -webkit-text-size-adjust:none 13 | } 14 | 15 | .hljs-code { 16 | color: <$macrocall $name="color-lightness" color="#8cb941" value={{$:/themes/cdr/captivate/settings/text-on-dark}} />; 17 | } 18 | 19 | .hljs-comment, 20 | .hljs-quote { 21 | color: #8da5be; 22 | } 23 | 24 | /* Solarized Green */ 25 | .hljs-keyword, 26 | .hljs-selector-tag, 27 | .hljs-addition { 28 | color: <$macrocall $name="color-lightness" color="#859900" value={{$:/themes/cdr/captivate/settings/text-on-dark}} />; 29 | } 30 | 31 | /* Solarized Cyan */ 32 | .hljs-number, 33 | .hljs-string, 34 | .hljs-meta .hljs-meta-string, 35 | .hljs-literal, 36 | .hljs-doctag, 37 | .hljs-regexp { 38 | color: <$macrocall $name="color-lightness" color="#2aa198" value={{$:/themes/cdr/captivate/settings/text-on-dark}} />; 39 | } 40 | 41 | /* Solarized Blue */ 42 | .hljs-title, 43 | .hljs-section, 44 | .hljs-name, 45 | .hljs-selector-id, 46 | .hljs-selector-class { 47 | color: <$macrocall $name="color-lightness" color="#268bd2" value={{$:/themes/cdr/captivate/settings/text-on-dark}} />; 48 | } 49 | 50 | /* Solarized Yellow */ 51 | .hljs-attribute, 52 | .hljs-attr, 53 | .hljs-variable, 54 | .hljs-template-variable, 55 | .hljs-class .hljs-title, 56 | .hljs-type { 57 | color: <$macrocall $name="color-lightness" color="#b58900" value={{$:/themes/cdr/captivate/settings/text-on-dark}} />; 58 | } 59 | 60 | /* Solarized Orange */ 61 | .hljs-symbol, 62 | .hljs-bullet, 63 | .hljs-subst, 64 | .hljs-meta, 65 | .hljs-meta .hljs-keyword, 66 | .hljs-selector-attr, 67 | .hljs-selector-pseudo, 68 | .hljs-operator, 69 | .hljs-link { 70 | color: <$macrocall $name="color-lightness" color="#cb4b16" value={{$:/themes/cdr/captivate/settings/text-on-dark}} />; 71 | } 72 | 73 | /* Solarized Red */ 74 | .hljs-template-tag, 75 | .hljs-built_in, 76 | .hljs-deletion { 77 | color: <$macrocall $name="color-lightness" color="#dc322f" value={{$:/themes/cdr/captivate/settings/text-on-dark}} />; 78 | } 79 | 80 | .hljs-formula { 81 | background: <$macrocall $name="color-lightness" color="#002a5a" value={{$:/themes/cdr/captivate/settings/text-on-dark}} />; 82 | } 83 | 84 | .hljs-emphasis { 85 | font-style: italic; 86 | } 87 | 88 | .hljs-strong { 89 | font-weight: bold; 90 | } 91 | -------------------------------------------------------------------------------- /themes/cdr/captivate/tweaks/themetweaks.tid: -------------------------------------------------------------------------------- 1 | type: text/vnd.tiddlywiki 2 | title: $:/themes/cdr/captivate/tweaks/theme 3 | tags: $:/tags/ControlPanel/Appearance 4 | caption: Theme Tweaks 5 | 6 | \define lingo-base() $:/language/ThemeTweaks/ 7 | 8 | ! Colors 9 | 10 | {{$:/themes/cdr/captivate/tweaks/colors}} 11 | 12 | ! <> 13 | 14 | |<$link to="$:/themes/tiddlywiki/vanilla/options/stickytitles"><>
//Causes tiddler titles to "stick" to the top of the browser window. Caution: Not compatible with all browsers// |<$select tiddler="$:/themes/tiddlywiki/vanilla/options/stickytitles"> | 15 | |<$link to="$:/themes/tiddlywiki/vanilla/options/codewrapping"><> |<$select tiddler="$:/themes/tiddlywiki/vanilla/options/codewrapping"> | 16 | 17 | ! <> 18 | 19 | |<$link to="$:/themes/tiddlywiki/vanilla/settings/fontfamily"><> |<$edit-text tiddler="$:/themes/tiddlywiki/vanilla/settings/fontfamily" default="" tag="input"/> | 20 | |<$link to="$:/themes/tiddlywiki/vanilla/settings/codefontfamily"><> |<$edit-text tiddler="$:/themes/tiddlywiki/vanilla/settings/codefontfamily" default="Incosolata LGC" tag="input"/> | 21 | |<$link to="$:/themes/tiddlywiki/vanilla/settings/editorfontfamily"><> |<$edit-text tiddler="$:/themes/tiddlywiki/vanilla/settings/editorfontfamily" default="" tag="input"/> | 22 | 23 | ! <> 24 | 25 | |<$link to="$:/themes/tiddlywiki/vanilla/metrics/fontsize"><> |<$edit-text tiddler="$:/themes/tiddlywiki/vanilla/metrics/fontsize" default="" tag="input"/> | 26 | |<$link to="$:/themes/tiddlywiki/vanilla/metrics/lineheight"><> |<$edit-text tiddler="$:/themes/tiddlywiki/vanilla/metrics/lineheight" default="" tag="input"/> | 27 | |<$link to="$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize"><> |<$edit-text tiddler="$:/themes/tiddlywiki/vanilla/metrics/bodyfontsize" default="" tag="input"/> | 28 | |<$link to="$:/themes/tiddlywiki/vanilla/metrics/bodylineheight"><> |<$edit-text tiddler="$:/themes/tiddlywiki/vanilla/metrics/bodylineheight" default="" tag="input"/> | 29 | |<$link to="$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint"><>
//<>// |^<$edit-text tiddler="$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint" default="" tag="input"/> | 30 | |<$link to="$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth"><>
//<>// |^<$edit-text tiddler="$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth" default="" tag="input"/> | 31 | |<$link to="$:/themes/cdr/captivate/settings/tiddlerwidth"><>
//<>// |^<$edit-text tiddler="$:/themes/cdr/captivate/settings/tiddlerwidth" default="" tag="input"/> | 32 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/action-wikifypalette.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | 3 | title: $:/plugins/cdr/colorlab/action-wikifypalette.js 4 | type: application/javascript 5 | module-type: widget 6 | 7 | Parse the given palette and converts all entry values to color strings--execute 8 | any macros/filters/transclusions if necessary. 9 | \*/ 10 | (function(){ 11 | 12 | /*jslint node: true, browser: true */ 13 | /*global $tw: false */ 14 | "use strict"; 15 | 16 | var Widget = require("$:/core/modules/widgets/widget.js").widget; 17 | var Color = require("$:/plugins/cdr/colorlab/lib/color.js"); 18 | var utils = require("$:/plugins/cdr/colorlab/twutils.js"); 19 | 20 | var WikifyPaletteWidget = function(parseTreeNode,options) { 21 | this.initialise(parseTreeNode,options); 22 | }; 23 | 24 | /* 25 | Inherit from the base widget class 26 | */ 27 | WikifyPaletteWidget.prototype = new Widget(); 28 | 29 | /* 30 | Render this widget into the DOM 31 | */ 32 | WikifyPaletteWidget.prototype.render = function(parent,nextSibling) { 33 | this.computeAttributes(); 34 | this.execute(); 35 | }; 36 | 37 | /* 38 | Compute the internal state of the widget 39 | */ 40 | WikifyPaletteWidget.prototype.execute = function() { 41 | this.srcTiddler = this.getAttribute("palette",this.wiki.getTiddlerText("$:/palette")); 42 | this.dstTiddler = this.getAttribute("save","$:/state/wikified-palette"); 43 | }; 44 | 45 | /* 46 | Refresh the widget by ensuring our attributes are up to date 47 | */ 48 | WikifyPaletteWidget.prototype.refresh = function(changedTiddlers) { 49 | var changedAttributes = this.computeAttributes(); 50 | if(changedAttributes["$message"] || changedAttributes["$prompt"]) { 51 | this.refreshSelf(); 52 | return true; 53 | } 54 | return this.refreshChildren(changedTiddlers); 55 | }; 56 | 57 | /* 58 | Invoke the action associated with this widget 59 | */ 60 | WikifyPaletteWidget.prototype.invokeAction = function(triggeringWidget,event) { 61 | var srcTiddler = this.wiki.getTiddler(this.srcTiddler); 62 | 63 | if (! srcTiddler) { 64 | return true; 65 | } 66 | 67 | var data = this.wiki.getTiddlerData(srcTiddler); 68 | 69 | // rgba values where r,g,b in [0..255] 70 | var rgbaToHex = function(rgba) { 71 | if (!rgba || rgba.length < 4) { 72 | return null; 73 | } 74 | // scale alpha to 0..255 75 | var alpha = Math.round(rgba[3] * 255) 76 | var hex = [rgba[0],rgba[1],rgba[2],alpha].map(function(e) { 77 | return ("0" + e.toString(16)).slice(-2); 78 | }); 79 | 80 | var hexstr = "#" + hex.join(""); 81 | 82 | if (alpha == 255) { 83 | return hexstr.slice(0,7); 84 | } 85 | 86 | return hexstr; 87 | }; 88 | 89 | var macro = { 90 | body: '<$transclude tiddler="'+ this.srcTiddler + '" index="$name$"/>', 91 | params: [ {name: "name",default: ""} ] 92 | }; 93 | this.setVariable("colour",macro.body,macro.params,true); 94 | this.setVariable("color",macro.body,macro.params,true); 95 | 96 | for (var key in data) { 97 | var colorString = utils.wikifyText(data[key],this); 98 | var color = Color.parse(colorString); 99 | if (color && $tw.browser && color.space && color.space !== "rgb") { 100 | if (window.matchMedia("(color-gamut: p3)").matches) { 101 | colorString = (new Color(color)).toString("p3"); 102 | } else { 103 | colorString = (new Color(color)).toString("rgb"); 104 | } 105 | } 106 | 107 | data[key] = colorString; 108 | } 109 | 110 | var newFields = { 111 | title: this.dstTiddler, 112 | tags: "$:/tags/Palette", 113 | name: srcTiddler.fields.name, 114 | description: srcTiddler.fields.description, 115 | type: "application/x-tiddler-dictionary", 116 | source: this.srcTiddler 117 | }; 118 | newFields.text = $tw.utils.makeTiddlerDictionary(data); 119 | 120 | if(srcTiddler.fields['color-scheme']) { 121 | newFields['color-scheme'] = srcTiddler.fields['color-scheme']; 122 | } 123 | this.wiki.addTiddler(new $tw.Tiddler(this.wiki.getCreationFields(),newFields)); 124 | return true; // Action was invoked 125 | }; 126 | 127 | WikifyPaletteWidget.prototype.allowActionPropagation = function() { 128 | return false; 129 | }; 130 | 131 | exports["action-wikifypalette"] = WikifyPaletteWidget; 132 | 133 | })(); -------------------------------------------------------------------------------- /themes/cdr/captivate/defaults/DefaultCaptivateTan.tid: -------------------------------------------------------------------------------- 1 | title: $:/palettes/CaptivateTan 2 | name: Captivate Tan 3 | description: Your tan color palette 4 | source: $:/themes/cdr/captivate/palettes/CaptivateTan 5 | tags: $:/tags/Palette 6 | type: application/x-tiddler-dictionary 7 | color-scheme: light 8 | 9 | alert-background: #ffe476 10 | alert-border: #c0c0c0 11 | alert-highlight: #881122 12 | alert-muted-foreground: #7d7d7d 13 | background: #fbfbf2 14 | blockquote-bar: #d0d0d0 15 | button-background: #617bbc 16 | button-background-hover: #4d65a5 17 | button-foreground: #ffffff 18 | button-border: #617bbc 19 | code-background: #eceef0 20 | code-border: #eceef0 21 | code-foreground: #303030 22 | dirty-indicator: #ca0000 23 | download-background: #617bbc 24 | download-foreground: #ffffff 25 | dragger-background: #303030 26 | dragger-foreground: #fbfbf2 27 | dropdown-background: #FFFFFF 28 | dropdown-border: #FFFFFF 29 | dropdown-tab-background-selected: #ebebc9 30 | dropdown-tab-background: transparent 31 | dropzone-background: #ffdf80 32 | external-link-background-hover: inherit 33 | external-link-background-visited: inherit 34 | external-link-background: inherit 35 | external-link-foreground-hover: #4e6ecd 36 | external-link-foreground-visited: #4e6ecd 37 | external-link-foreground: #4e6ecd 38 | fab-background: #ece8d2 39 | fab-background-hover: #e8e1bc 40 | fab-foreground: #5875c0 41 | foreground: #303030 42 | message-background: #ecf2ff 43 | message-border: #c0c0c0 44 | message-foreground: #7d7d7d 45 | modal-backdrop: #303030 46 | modal-background: #fbfbf2 47 | modal-border: #c0c0c0 48 | modal-footer-background: #f5f5f5 49 | modal-footer-border: #ddd 50 | modal-header-border: #eee 51 | muted-foreground: #7d7d7d 52 | notification-background: #d6e3ff 53 | notification-border: #7590d2 54 | page-background: #f5f2e4 55 | pre-background: #eceef0 56 | pre-border: #eceef0 57 | primary: #617bbc 58 | secondary-button-background: #dce5ff 59 | secondary-button-foreground: #3a508e 60 | secondary-button-border: #7590d2 61 | selection-background: #dce5ff 62 | selection-foreground: #303030 63 | sidebar-button-foreground: #ffffff 64 | sidebar-controls-foreground-hover: #000000 65 | sidebar-controls-foreground: #aaaaaa 66 | sidebar-background: #fbfbf2 67 | sidebar-foreground-shadow: transparent 68 | sidebar-foreground: #303030 69 | sidebar-muted-foreground-hover: #303030 70 | sidebar-muted-foreground: #7d7d7d 71 | sidebar-tab-background-selected: #ebebc9 72 | sidebar-tab-background: transparent 73 | sidebar-tab-border-selected: #617bbc 74 | sidebar-tab-border: transparent 75 | sidebar-tab-divider: #c0c0c0 76 | sidebar-tab-foreground-selected: #5373d3 77 | sidebar-tab-foreground: #7d7d7d 78 | sidebar-tiddler-link-foreground-hover: #283f9b 79 | sidebar-tiddler-link-foreground: #4766c5 80 | site-title-foreground: #202020 81 | static-alert-foreground: #aaaaaa 82 | tab-background-selected: #ebebc9 83 | tab-background: transparent 84 | tab-border-selected: #617bbc 85 | tab-border: transparent 86 | tab-divider: #c0c0c0 87 | tab-foreground-selected: #303030 88 | tab-foreground: #7d7d7d 89 | table-border: #e0e0e0 90 | table-footer-background: rgba(0, 0, 0, 0.04) 91 | table-header-background: rgba(0, 0, 0, 0.1) 92 | tag-background: #e3ca7d 93 | tag-foreground: #3d2e00 94 | tiddler-background: #fbfbf2 95 | tiddler-border: #fbfbf2 96 | tiddler-controls-foreground-hover: #202020 97 | tiddler-controls-foreground-selected: #202020 98 | tiddler-controls-foreground: #c0c0c0 99 | tiddler-editor-background: #f6f6f6 100 | tiddler-editor-border-image: 101 | tiddler-editor-border: #d4d4d4 102 | tiddler-editor-fields-even: rgba(0, 0, 0, 0.1) 103 | tiddler-editor-fields-odd: rgba(0, 0, 0, 0.04) 104 | tiddler-info-background: #f1f1e9 105 | tiddler-info-border: #F5F5F5 106 | tiddler-info-tab-background: #ebebc9 107 | tiddler-link-background: #fbfbf2 108 | tiddler-link-foreground: #4e6ecd 109 | tiddler-subtitle-foreground: #7d7d7d 110 | tiddler-title-foreground: #303030 111 | toolbar-new-button: 112 | toolbar-options-button: 113 | toolbar-save-button: 114 | toolbar-info-button: 115 | toolbar-edit-button: 116 | toolbar-close-button: 117 | toolbar-delete-button: 118 | toolbar-cancel-button: 119 | toolbar-done-button: 120 | untagged-background: #7d7d7d 121 | very-muted-foreground: #c0c0c0 -------------------------------------------------------------------------------- /themes/cdr/captivate/defaults/DefaultCaptivateDark.tid: -------------------------------------------------------------------------------- 1 | title: $:/palettes/CaptivateDark 2 | name: Captivate Dark 3 | description: Your dark themed palette 4 | source: $:/themes/cdr/captivate/palettes/CaptivateDark 5 | tags: $:/tags/Palette 6 | type: application/x-tiddler-dictionary 7 | color-scheme: dark 8 | 9 | alert-background: #660015 10 | alert-border: #808080 11 | alert-highlight: #ff8b69 12 | alert-muted-foreground: #bababa 13 | background: #1d2442 14 | blockquote-bar: #505050 15 | button-background: #5778d8 16 | button-background-hover: #6e8dde 17 | button-foreground: #ffffff 18 | button-border: #5778d8 19 | code-background: #545d7f 20 | code-border: #545d7f 21 | code-foreground: #c6c6c6 22 | dirty-indicator: #d60000 23 | download-background: #5778d8 24 | download-foreground: #ffffff 25 | dragger-background: #c6c6c6 26 | dragger-foreground: #1d2442 27 | dropdown-background: #1b1b20 28 | dropdown-border: #47474d 29 | dropdown-tab-background-selected: 30 | dropdown-tab-background: transparent 31 | dropzone-background: #3d2e00 32 | external-link-background-hover: inherit 33 | external-link-background-visited: inherit 34 | external-link-background: inherit 35 | external-link-foreground-hover: #7ea1ff 36 | external-link-foreground-visited: #7ea1ff 37 | external-link-foreground: #7ea1ff 38 | fab-background-hover: #3c59b7 39 | foreground: #c6c6c6 40 | message-background: #014272 41 | message-border: #014272 42 | message-foreground: #c6c6c6 43 | modal-backdrop: #000d28 44 | modal-background: #1d2442 45 | modal-border: #808080 46 | modal-footer-background: #464646 47 | modal-footer-border: #808080 48 | modal-header-border: #808080 49 | muted-foreground: #ababab 50 | notification-background: #324ca9 51 | notification-border: #6a8eef 52 | page-background: #000d28 53 | pre-background: #545d7f 54 | pre-border: #545d7f 55 | primary: #5778d8 56 | secondary-button-background: #1b2e89 57 | secondary-button-background-hover: #27409b 58 | secondary-button-foreground: #b0c1f1 59 | secondary-button-border: #6a8eef 60 | selection-background: #263d99 61 | selection-foreground: #c6c6c6 62 | sidebar-button-foreground: #ffffff 63 | sidebar-controls-foreground-hover: #e3e3e3 64 | sidebar-controls-foreground: #aaaaaa 65 | sidebar-background: #1d2442 66 | sidebar-foreground-shadow: transparent 67 | sidebar-foreground: #c6c6c6 68 | sidebar-muted-foreground-hover: #c6c6c6 69 | sidebar-muted-foreground: #ababab 70 | sidebar-tab-background-selected: rgba(36,58,150,0.75) 71 | sidebar-tab-background: transparent 72 | sidebar-tab-border-selected: #6a8eef 73 | sidebar-tab-border: transparent 74 | sidebar-tab-divider: #585858 75 | sidebar-tab-foreground-selected: #ffffff 76 | sidebar-tab-foreground: #ababab 77 | sidebar-tiddler-link-foreground-hover: #9cb8ff 78 | sidebar-tiddler-link-foreground: #89aaff 79 | site-title-foreground: #b2b2b2 80 | static-alert-foreground: #B48EAD 81 | tab-background-selected: rgba(36,58,150,0.75) 82 | tab-background: transparent 83 | tab-border-selected: #6a8eef 84 | tab-border: #585858 85 | tab-divider: #585858 86 | tab-foreground-selected: #ffffff 87 | tab-foreground: #ababab 88 | table-border: #535353 89 | table-footer-background: rgba(255, 255, 255, 0.09) 90 | table-header-background: rgba(255, 255, 255, 0.17) 91 | tag-background: #eecc66 92 | tag-foreground: #3d2e00 93 | tiddler-background: #1d2442 94 | tiddler-border: #1d2442 95 | tiddler-controls-foreground-hover: #d0d0d0 96 | tiddler-controls-foreground-selected: #c0c0c0 97 | tiddler-controls-foreground: #6e799b 98 | tiddler-editor-background: #121212 99 | tiddler-editor-border-image: 100 | tiddler-editor-border: #4c4c4c 101 | tiddler-editor-fields-even: rgba(255, 255, 255, 0.17) 102 | tiddler-editor-fields-odd: rgba(255, 255, 255, 0.09) 103 | tiddler-info-background: #282f4a 104 | tiddler-info-border: #282f4a 105 | tiddler-info-tab-background: rgba(36,58,150,0.75) 106 | tiddler-link-background: #1d2442 107 | tiddler-link-foreground: #7ea1ff 108 | tiddler-subtitle-foreground: #bababa 109 | tiddler-title-foreground: #c6c6c6 110 | toolbar-new-button: 111 | toolbar-options-button: 112 | toolbar-save-button: 113 | toolbar-info-button: 114 | toolbar-edit-button: 115 | toolbar-close-button: 116 | toolbar-delete-button: 117 | toolbar-cancel-button: 118 | toolbar-done-button: 119 | untagged-background: #808080 120 | very-muted-foreground: #808080 -------------------------------------------------------------------------------- /themes/cdr/captivate/defaults/DefaultCaptivateLight.tid: -------------------------------------------------------------------------------- 1 | title: $:/palettes/CaptivateLight 2 | name: Captivate Light 3 | description: Your light themed palette 4 | source: $:/themes/cdr/captivate/palettes/CaptivateLight 5 | tags: $:/tags/Palette 6 | type: application/x-tiddler-dictionary 7 | color-scheme: light 8 | 9 | alert-background: #ffe476 10 | alert-border: #c0c0c0 11 | alert-highlight: #881122 12 | alert-muted-foreground: #707070 13 | background: #fefeff 14 | blockquote-bar: #d0d0d0 15 | button-background: #5f7fda 16 | button-background-hover: #4c6ac3 17 | button-foreground: #ffffff 18 | button-border: #5f7fda 19 | code-background: #edeff1 20 | code-border: #edeff1 21 | code-foreground: #202020 22 | dirty-indicator: #ca0000 23 | download-background: #5f7fda 24 | download-foreground: #ffffff 25 | dragger-background: #202020 26 | dragger-foreground: #fefeff 27 | dropdown-background: #FFFFFF 28 | dropdown-border: #FFFFFF 29 | dropdown-tab-background-selected: rgba(156,184,255,0.3) 30 | dropdown-tab-background: transparent 31 | dropzone-background: #ffdf80 32 | external-link-background-hover: inherit 33 | external-link-background-visited: inherit 34 | external-link-background: inherit 35 | external-link-foreground-hover: #4e6ecd 36 | external-link-foreground-visited: #4e6ecd 37 | external-link-foreground: #4e6ecd 38 | fab-background: #d5dff9 39 | fab-background-hover: #c8d7ff 40 | fab-foreground: #4766c5 41 | foreground: #202020 42 | message-background: #ecf2ff 43 | message-border: #c0c0c0 44 | message-foreground: #707070 45 | modal-backdrop: #202020 46 | modal-background: #fefeff 47 | modal-border: #c0c0c0 48 | modal-footer-background: #f5f5f5 49 | modal-footer-border: #ddd 50 | modal-header-border: #eee 51 | muted-foreground: #707070 52 | notification-background: #d6e3ff 53 | notification-border: #6a8eef 54 | page-background: #e7ecff 55 | pre-background: #edeff1 56 | pre-border: #edeff1 57 | primary: #5778d8 58 | secondary-button-background: #dce5ff 59 | secondary-button-foreground: #324ca9 60 | secondary-button-border: #6a8eef 61 | selection-background: #dce5ff 62 | selection-foreground: #202020 63 | sidebar-button-foreground: #ffffff 64 | sidebar-controls-foreground-hover: #000000 65 | sidebar-controls-foreground: #aaaaaa 66 | sidebar-background: #fefeff 67 | sidebar-foreground-shadow: transparent 68 | sidebar-foreground: #202020 69 | sidebar-muted-foreground-hover: #202020 70 | sidebar-muted-foreground: #707070 71 | sidebar-tab-background-selected: rgba(156,184,255,0.3) 72 | sidebar-tab-background: transparent 73 | sidebar-tab-border-selected: #5778d8 74 | sidebar-tab-border: transparent 75 | sidebar-tab-divider: #c0c0c0 76 | sidebar-tab-foreground-selected: #283f9b 77 | sidebar-tab-foreground: #707070 78 | sidebar-tiddler-link-foreground-hover: #283f9b 79 | sidebar-tiddler-link-foreground: #4766c5 80 | site-title-foreground: #202020 81 | static-alert-foreground: #aaaaaa 82 | tab-background-selected: rgba(156,184,255,0.3) 83 | tab-background: transparent 84 | tab-border-selected: #5778d8 85 | tab-border: transparent 86 | tab-divider: #c0c0c0 87 | tab-foreground-selected: #202020 88 | tab-foreground: #707070 89 | table-border: #e0e0e0 90 | table-footer-background: rgba(0, 0, 0, 0.04) 91 | table-header-background: rgba(0, 0, 0, 0.1) 92 | tag-background: #eecc66 93 | tag-foreground: #3d2e00 94 | tiddler-background: #fefeff 95 | tiddler-border: #fefeff 96 | tiddler-controls-foreground-hover: #202020 97 | tiddler-controls-foreground-selected: #202020 98 | tiddler-controls-foreground: #c0c0c0 99 | tiddler-editor-background: #f6f8fa 100 | tiddler-editor-border-image: 101 | tiddler-editor-border: #d4d4d4 102 | tiddler-editor-fields-even: rgba(0, 0, 0, 0.1) 103 | tiddler-editor-fields-odd: rgba(0, 0, 0, 0.04) 104 | tiddler-info-background: #F5F5F5 105 | tiddler-info-border: #F5F5F5 106 | tiddler-info-tab-background: rgba(156,184,255,0.3) 107 | tiddler-link-background: #fefeff 108 | tiddler-link-foreground: #4e6ecd 109 | tiddler-subtitle-foreground: #707070 110 | tiddler-title-foreground: #202020 111 | toolbar-new-button: 112 | toolbar-options-button: 113 | toolbar-save-button: 114 | toolbar-info-button: 115 | toolbar-edit-button: 116 | toolbar-close-button: 117 | toolbar-delete-button: 118 | toolbar-cancel-button: 119 | toolbar-done-button: 120 | untagged-background: #707070 121 | very-muted-foreground: #c0c0c0 -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/AdvancedSearch/System.tid: -------------------------------------------------------------------------------- 1 | title: $:/core/ui/AdvancedSearch/System 2 | tags: $:/tags/AdvancedSearch 3 | caption: {{$:/language/Search/System/Caption}} 4 | first-search-filter: [is[system]searchsort[title]limit[250]] -[[$:/temp/advancedsearch]] -[prefix[$:/temp/advancedsearch/input]] -[[$:/temp/advancedsearch/selected-item]] 5 | 6 | \define lingo-base() $:/language/Search/ 7 | \define set-next-input-tab(beforeafter:"after",stateTitle,tag,defaultState,currentTabTiddler) 8 | <$macrocall $name="change-input-tab" 9 | stateTitle="$:/state/tab--1498284803" 10 | tag="$:/tags/AdvancedSearch" 11 | beforeafter="$beforeafter$" 12 | defaultState="$:/core/ui/AdvancedSearch/System" 13 | actions="<$action-setfield $tiddler='$:/state/advancedsearch/currentTab' text=<>/>"/> 14 | \end 15 | 16 | \define cancel-search-actions() 17 | \whitespace trim 18 | <$list 19 | filter="[{$:/temp/advancedsearch}!match{$:/temp/advancedsearch/input}]" 20 | emptyMessage="<$action-deletetiddler $filter='[[$:/temp/advancedsearch]] [[$:/temp/advancedsearch/input]] [[$:/temp/advancedsearch/selected-item]]' />"> 21 | <$action-setfield $tiddler="$:/temp/advancedsearch/input" text={{$:/temp/advancedsearch}}/> 22 | <$action-setfield $tiddler="$:/temp/advancedsearch/refresh" text="yes" /> 23 | 24 | <$action-sendmessage $message="tm-focus-selector" $param=".tc-advanced-search input"/> 25 | \end 26 | 27 | \define input-accept-actions() 28 | \whitespace trim 29 | <$list 30 | filter="[{$:/config/Search/NavigateOnEnter/enable}match[yes]]" 31 | emptyMessage="<$list filter='[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]'><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/>"> 32 | <$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/> 33 | 34 | \end 35 | 36 | \define input-accept-variant-actions() 37 | \whitespace trim 38 | <$list 39 | filter="[{$:/config/Search/NavigateOnEnter/enable}match[yes]]" 40 | emptyMessage="<$list filter='[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]'><$list filter='[<__tiddler__>get[text]minlength[1]]'><$action-sendmessage $message='tm-edit-tiddler' $param={{{ [<__tiddler__>get[text]] }}}/>"> 41 | <$list filter="[<__tiddler__>get[text]minlength[1]]"> 42 | <$action-sendmessage $message="tm-edit-tiddler" $param={{{ [<__tiddler__>get[text]] }}}/> 43 | 44 | \end 45 | 46 | \whitespace trim 47 | 48 | <> 49 | 50 | 76 | 77 | <$reveal state="$:/temp/advancedsearch" type="nomatch" text=""> 78 | <$let 79 | userInput={{$:/temp/advancedsearch}} 80 | resultCount="<$count filter={{$:/core/ui/AdvancedSearch/System!!first-search-filter}} />"> 81 | <$list filter="[{$:/temp/advancedsearch}minlength{$:/config/Search/MinLength}limit[1]]" emptyMessage="
{{$:/language/Search/Search/TooShort}}
" variable="listItem"> 82 | 83 |
84 | 85 | <> 86 | 87 | <$list filter={{$:/core/ui/AdvancedSearch/System!!first-search-filter}}> 88 | addsuffix[-primaryList]] -[[$:/temp/advancedsearch/selected-item]get[text]] +[then[]else[tc-list-item-selected]] }}}> 89 | <$transclude tiddler="$:/core/ui/ListItemTemplate"/> 90 | 91 | 92 | 93 |
94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /themes/cdr/captivate/ui/TopBarSearch.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/ui/TopBar/Search 2 | 3 | \whitespace trim 4 | \define set-next-input-tab(beforeafter:"after") <$macrocall $name="change-input-tab" stateTitle="$:/state/tab/topbar-search" tag="$:/tags/AdvancedSearch" beforeafter="$beforeafter$" defaultState="$:/core/ui/AdvancedSearch/Standard" actions="<$action-setfield $tiddler='$:/state/advancedsearch/currentTab' text=<>/>"/> 5 | 6 | \define advanced-search-actions() 7 | <$action-setfield $tiddler="$:/temp/advancedsearch" text={{{ [get[text]] }}}/> 8 | <$action-setfield $tiddler="$:/temp/advancedsearch/input" text={{{ [get[text]] }}}/> 9 | <$action-navigate $to="$:/AdvancedSearch"/> 10 | <$action-setfield $tiddler="$:/temp/advancedsearch/refresh" text="yes"/> 11 | <$action-sendmessage $message="tm-focus-selector" $param="""[data-tiddler-title="$:/AdvancedSearch"] .tc-search input""" preventScroll="true"/> 12 | <$action-deletetiddler $filter="[]"/> 13 | \end 14 | 15 | \define cancel-search-actions() 16 | <$set name="userInput" value={{{ [<__storeTitle__>get[text]] }}}> 17 | <$list filter="[<__tiddler__>get[text]!match]" emptyMessage="""<$action-deletetiddler $filter="[<__storeTitle__>] [<__tiddler__>] [<__selectionStateTitle__>]"/>"""> 18 | <$action-setfield $tiddler=<<__tiddler__>> text=<>/><$action-setfield $tiddler=<<__refreshTitle__>> text="yes" /> 19 | 20 | 21 | \end 22 | 23 | \define input-accept-actions() 24 | <$list filter="[{$:/config/Search/NavigateOnEnter/enable}match[yes]]" emptyMessage="""<$list filter="[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]"> 25 | <$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/>"""><$action-navigate $to={{{ [<__tiddler__>get[text]] }}}/> 26 | 27 | \end 28 | 29 | \define input-accept-variant-actions() 30 | <$list filter="[{$:/config/Search/NavigateOnEnter/enable}match[yes]]" emptyMessage="""<$list filter="[<__tiddler__>get[text]!is[missing]] ~[<__tiddler__>get[text]is[shadow]]"><$list filter="[<__tiddler__>get[text]minlength[1]]"><$action-sendmessage $message="tm-edit-tiddler" $param={{{ [<__tiddler__>get[text]] }}}/>"""> 31 | <$list filter="[<__tiddler__>get[text]minlength[1]]"><$action-sendmessage $message="tm-edit-tiddler" $param={{{ [<__tiddler__>get[text]] }}}/> 32 | 33 | \end 34 | 35 | <$vars searchTiddler="$:/temp/advancedsearch/input/topbar" > 36 | 95 | 96 | -------------------------------------------------------------------------------- /themes/cdr/captivate/palettes/CaptivateTan.tid: -------------------------------------------------------------------------------- 1 | type: application/x-tiddler-dictionary 2 | title: $:/themes/cdr/captivate/palettes/CaptivateTan 3 | name: Captivate Tan 4 | description: Your tan color palette 5 | color-scheme: light 6 | 7 | alert-background: #ffe476 8 | alert-border: <> 9 | alert-highlight: #881122 10 | alert-muted-foreground: <> 11 | background: #fbfbf2 12 | blockquote-bar: #d0d0d0 13 | button-background: <> 14 | button-background-hover: {{{ [colour[button-background]deviate[]] }}} 15 | button-foreground: {{{ [colour[button-background]autocontrast[]] }}} 16 | button-border: <> 17 | code-background: #eceef0 18 | code-border: <> 19 | code-foreground: <> 20 | dirty-indicator: #ca0000 21 | download-background: <> 22 | download-foreground: <> 23 | dragger-background: <> 24 | dragger-foreground: <> 25 | dropdown-background: #FFFFFF 26 | dropdown-border: <> 27 | dropdown-tab-background-selected: <> 28 | dropdown-tab-background: transparent 29 | dropzone-background: {{{ [{$:/themes/cdr/captivate/settings/color-secondary}lightness[90]] }}} 30 | external-link-background-hover: inherit 31 | external-link-background-visited: inherit 32 | external-link-background: inherit 33 | external-link-foreground-hover: <> 34 | external-link-foreground-visited: <> 35 | external-link-foreground: <> 36 | fab-background: #ece8d2 37 | fab-background-hover: {{{ [colour[fab-background]deviate[]] }}} 38 | fab-foreground: {{{ [colour[tiddler-link-foreground]mix,[.65]lightness[50]] }}} 39 | foreground: #303030 40 | message-background: #ecf2ff 41 | message-border: <> 42 | message-foreground: <> 43 | modal-backdrop: <> 44 | modal-background: <> 45 | modal-border: <> 46 | modal-footer-background: #f5f5f5 47 | modal-footer-border: #ddd 48 | modal-header-border: #eee 49 | muted-foreground: #7d7d7d 50 | notification-background: <$macrocall $name="color-lightness" color=<> value="90" /> 51 | notification-border: <> 52 | page-background: #f5f2e4 53 | pre-background: <> 54 | pre-border: <> 55 | primary: {{{ [{$:/themes/cdr/captivate/settings/color-primary}mute[]lightness[range(30,92)]] }}} 56 | secondary-button-background: {{{ [colour[primary]alpha[0.4]over[#ffffff]lightness[91]] }}} 57 | secondary-button-foreground: <$macrocall $name="color-lightness" color=<> value="35" /> 58 | secondary-button-border: <$macrocall $name="color-lightness" color=<> value="60" /> 59 | selection-background: {{{ [colour[primary]alpha[0.4]over[#ffffff]lightness[91]] }}} 60 | selection-foreground: <> 61 | sidebar-button-foreground: <> 62 | sidebar-controls-foreground-hover: #000000 63 | sidebar-controls-foreground: #aaaaaa 64 | sidebar-background: <> 65 | sidebar-foreground-shadow: transparent 66 | sidebar-foreground: <> 67 | sidebar-muted-foreground-hover: <> 68 | sidebar-muted-foreground: <> 69 | sidebar-tab-background-selected: <> 70 | sidebar-tab-background: transparent 71 | sidebar-tab-border-selected: <> 72 | sidebar-tab-border: transparent 73 | sidebar-tab-divider: <> 74 | sidebar-tab-foreground-selected: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-primary}} value="max(50)" /> 75 | sidebar-tab-foreground: <> 76 | sidebar-tiddler-link-foreground-hover: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-primary}} value="30" /> 77 | sidebar-tiddler-link-foreground: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-primary}} value="45" /> 78 | site-title-foreground: #202020 79 | static-alert-foreground: #aaaaaa 80 | tab-background-selected: #ebebc9 81 | tab-background: transparent 82 | tab-border-selected: {{{ [colour[primary]lightness[max(70)]] }}} 83 | tab-border: transparent 84 | tab-divider: #c0c0c0 85 | tab-foreground-selected: <> 86 | tab-foreground: <> 87 | table-border: #e0e0e0 88 | table-footer-background: <> 89 | table-header-background: <> 90 | tag-background: {{{ [{$:/themes/cdr/captivate/settings/color-secondary}mute[]lightness[max(90)]] }}} 91 | tag-foreground: <$macrocall $name="color-autocontrast" color={{$:/themes/cdr/captivate/settings/color-secondary}} /> 92 | tiddler-background: <> 93 | tiddler-border: <> 94 | tiddler-controls-foreground-hover: #202020 95 | tiddler-controls-foreground-selected: #202020 96 | tiddler-controls-foreground: <> 97 | tiddler-editor-background: #f6f6f6 98 | tiddler-editor-border-image: 99 | tiddler-editor-border: <$macrocall $name="color-lightness" color=<> value="85" /> 100 | tiddler-editor-fields-even: rgba(0, 0, 0, 0.1) 101 | tiddler-editor-fields-odd: rgba(0, 0, 0, 0.04) 102 | tiddler-info-background: <$macrocall $name="color-mix" color1=<> color2="#9f9f9f" weight="0.1" /> 103 | tiddler-info-border: #F5F5F5 104 | tiddler-info-tab-background: <> 105 | tiddler-link-background: <> 106 | tiddler-link-foreground: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-link}} value={{$:/themes/cdr/captivate/settings/text-on-light}} /> 107 | tiddler-subtitle-foreground: <> 108 | tiddler-title-foreground: <> 109 | toolbar-new-button: 110 | toolbar-options-button: 111 | toolbar-save-button: 112 | toolbar-info-button: 113 | toolbar-edit-button: 114 | toolbar-close-button: 115 | toolbar-delete-button: 116 | toolbar-cancel-button: 117 | toolbar-done-button: 118 | untagged-background: <> 119 | very-muted-foreground: #c0c0c0 120 | -------------------------------------------------------------------------------- /themes/cdr/captivate/palettes/CaptivateLight.tid: -------------------------------------------------------------------------------- 1 | type: application/x-tiddler-dictionary 2 | title: $:/themes/cdr/captivate/palettes/CaptivateLight 3 | name: Captivate Light 4 | description: Your light themed palette 5 | color-scheme: light 6 | 7 | alert-background: #ffe476 8 | alert-border: <> 9 | alert-highlight: #881122 10 | alert-muted-foreground: <> 11 | background: {{{ [colour[primary]lightness[99.8]] }}} 12 | blockquote-bar: #d0d0d0 13 | button-background: {{{ [colour[primary]lightness[max(93)]alpha[0.95]over[#fff]] }}} 14 | button-background-hover: {{{ [colour[button-background]deviate[]] }}} 15 | button-foreground: {{{ [colour[button-background]autocontrast[]] }}} 16 | button-border: <> 17 | code-background: #edeff1 18 | code-border: <> 19 | code-foreground: <> 20 | dirty-indicator: #ca0000 21 | download-background: <> 22 | download-foreground: <> 23 | dragger-background: <> 24 | dragger-foreground: <> 25 | dropdown-background: #FFFFFF 26 | dropdown-border: <> 27 | dropdown-tab-background-selected: <> 28 | dropdown-tab-background: transparent 29 | dropzone-background: {{{ [{$:/themes/cdr/captivate/settings/color-secondary}lightness[90]] }}} 30 | external-link-background-hover: inherit 31 | external-link-background-visited: inherit 32 | external-link-background: inherit 33 | external-link-foreground-hover: <> 34 | external-link-foreground-visited: <> 35 | external-link-foreground: <> 36 | fab-background: {{{ [colour[primary]lightness[70]alpha[0.2]over] }}} 37 | fab-background-hover: {{{ [colour[fab-background]deviate[]] }}} 38 | fab-foreground: {{{ [colour[primary]lightness[45]] }}} 39 | foreground: #202020 40 | message-background: #ecf2ff 41 | message-border: <> 42 | message-foreground: <> 43 | modal-backdrop: <> 44 | modal-background: <> 45 | modal-border: <> 46 | modal-footer-background: #f5f5f5 47 | modal-footer-border: #ddd 48 | modal-header-border: #eee 49 | muted-foreground: #707070 50 | notification-background: <$macrocall $name="color-lightness" color=<> value="90" /> 51 | notification-border: <> 52 | page-background: {{{ [colour[primary]alpha[.19]over[#f8f8f8]lightness[93.5]] }}} 53 | pre-background: <> 54 | pre-border: <> 55 | primary: {{{ [{$:/themes/cdr/captivate/settings/color-primary}] }}} 56 | secondary-button-background: {{{ [colour[primary]alpha[0.4]over[#ffffff]lightness[91]] }}} 57 | secondary-button-foreground: <$macrocall $name="color-lightness" color=<> value="35" /> 58 | secondary-button-border: <$macrocall $name="color-lightness" color=<> value="60" /> 59 | selection-background: {{{ [colour[primary]alpha[0.4]over[#ffffff]lightness[91]] }}} 60 | selection-foreground: <> 61 | sidebar-button-foreground: <> 62 | sidebar-controls-foreground-hover: #000000 63 | sidebar-controls-foreground: #aaaaaa 64 | sidebar-background: <> 65 | sidebar-foreground-shadow: transparent 66 | sidebar-foreground: <> 67 | sidebar-muted-foreground-hover: <> 68 | sidebar-muted-foreground: <> 69 | sidebar-tab-background-selected: <> 70 | sidebar-tab-background: transparent 71 | sidebar-tab-border-selected: <> 72 | sidebar-tab-border: transparent 73 | sidebar-tab-divider: <> 74 | sidebar-tab-foreground-selected: {{{ [colour[primary]lightness[30]] }}} 75 | sidebar-tab-foreground: <> 76 | sidebar-tiddler-link-foreground-hover: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-primary}} value="30" /> 77 | sidebar-tiddler-link-foreground: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-primary}} value="45" /> 78 | site-title-foreground: #202020 79 | static-alert-foreground: #aaaaaa 80 | tab-background-selected: {{{ [colour[primary]lightness[75]alpha[0.3]] }}} 81 | tab-background: transparent 82 | tab-border-selected: {{{ [colour[primary]lightness[max(70)]] }}} 83 | tab-border: transparent 84 | tab-divider: #c0c0c0 85 | tab-foreground-selected: <> 86 | tab-foreground: <> 87 | table-border: #e0e0e0 88 | table-footer-background: <> 89 | table-header-background: <> 90 | tag-background: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-secondary}} value="max(92)" /> 91 | tag-foreground: <$macrocall $name="color-autocontrast" color={{$:/themes/cdr/captivate/settings/color-secondary}} /> 92 | tiddler-background: <> 93 | tiddler-border: <> 94 | tiddler-controls-foreground-hover: #202020 95 | tiddler-controls-foreground-selected: #202020 96 | tiddler-controls-foreground: <> 97 | tiddler-editor-background: #f6f8fa 98 | tiddler-editor-border-image: 99 | tiddler-editor-border: <$macrocall $name="color-lightness" color=<> value="85" /> 100 | tiddler-editor-fields-even: rgba(0, 0, 0, 0.1) 101 | tiddler-editor-fields-odd: rgba(0, 0, 0, 0.04) 102 | tiddler-info-background: #F5F5F5 103 | tiddler-info-border: #F5F5F5 104 | tiddler-info-tab-background: <> 105 | tiddler-link-background: <> 106 | tiddler-link-foreground: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-link}} value={{$:/themes/cdr/captivate/settings/text-on-light}} /> 107 | tiddler-subtitle-foreground: <> 108 | tiddler-title-foreground: <> 109 | toolbar-new-button: 110 | toolbar-options-button: 111 | toolbar-save-button: 112 | toolbar-info-button: 113 | toolbar-edit-button: 114 | toolbar-close-button: 115 | toolbar-delete-button: 116 | toolbar-cancel-button: 117 | toolbar-done-button: 118 | untagged-background: <> 119 | very-muted-foreground: #c0c0c0 120 | -------------------------------------------------------------------------------- /themes/cdr/captivate/palettes/CaptivateDark.tid: -------------------------------------------------------------------------------- 1 | type: application/x-tiddler-dictionary 2 | title: $:/themes/cdr/captivate/palettes/CaptivateDark 3 | name: Captivate Dark 4 | description: Your dark themed palette 5 | color-scheme: dark 6 | 7 | alert-background: #660015 8 | alert-border: <> 9 | alert-highlight: #ff8b69 10 | alert-muted-foreground: <> 11 | background: {{{ [colour[primary]lightness[30]alpha[0.3]over[#030303]lightness[15]] }}} 12 | blockquote-bar: #505050 13 | button-background: <> 14 | button-background-hover: {{{ [colour[button-background]mix[#fff],[.15]] }}} 15 | button-foreground: {{{ [colour[button-background]autocontrast[]] }}} 16 | button-border: <> 17 | code-background: {{{ [colour[background]lightness[+25]] }}} 18 | code-border: <> 19 | code-foreground: <> 20 | dirty-indicator: #d60000 21 | download-background: <> 22 | download-foreground: <> 23 | dragger-background: <> 24 | dragger-foreground: <> 25 | dropdown-background: #1b1b20 26 | dropdown-border: {{{ [colour[dropdown-background]deviate[]] }}} 27 | dropdown-tab-background-selected: <> 28 | dropdown-tab-background: transparent 29 | dropzone-background: {{{ [{$:/themes/cdr/captivate/settings/color-secondary}lightness[20]] }}} 30 | external-link-background-hover: inherit 31 | external-link-background-visited: inherit 32 | external-link-background: inherit 33 | external-link-foreground-hover: <> 34 | external-link-foreground-visited: <> 35 | external-link-foreground: <> 36 | fab-background-hover: {{{ [colour[primary]lightness[40]] }}} 37 | foreground: #c6c6c6 38 | message-background: #014272 39 | message-border: <> 40 | message-foreground: <> 41 | modal-backdrop: <> 42 | modal-background: <> 43 | modal-border: <> 44 | modal-footer-background: #464646 45 | modal-footer-border: <> 46 | modal-header-border: <> 47 | muted-foreground: #ababab 48 | notification-background: <$macrocall $name="color-lightness" color=<> value="35" /> 49 | notification-border: <> 50 | page-background: {{{ [colour[background]lightness[-11]] }}} 51 | pre-background: <> 52 | pre-border: <> 53 | primary: {{{ [{$:/themes/cdr/captivate/settings/color-primary}lightness[range(30,85)]] }}} 54 | secondary-button-background: {{{ [colour[primary]lightness[23]] }}} 55 | secondary-button-background-hover: {{{ [colour[secondary-button-background]lightness[30]] }}} 56 | secondary-button-foreground: {{{ [colour[primary]alpha[0.5]over[#ffffff]lightness[78]] }}} 57 | secondary-button-border: <$macrocall $name="color-lightness" color=<> value="60" /> 58 | selection-background: {{{ [colour[primary]lightness[29]] }}} 59 | selection-foreground: <> 60 | sidebar-button-foreground: <> 61 | sidebar-controls-foreground-hover: #e3e3e3 62 | sidebar-controls-foreground: #aaaaaa 63 | sidebar-background: <> 64 | sidebar-foreground-shadow: transparent 65 | sidebar-foreground: <> 66 | sidebar-muted-foreground-hover: <> 67 | sidebar-muted-foreground: <> 68 | sidebar-tab-background-selected: <> 69 | sidebar-tab-background: transparent 70 | sidebar-tab-border-selected: <> 71 | sidebar-tab-border: transparent 72 | sidebar-tab-divider: <> 73 | sidebar-tab-foreground-selected: <> 74 | sidebar-tab-foreground: <> 75 | sidebar-tiddler-link-foreground-hover: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-primary}} value="75" /> 76 | sidebar-tiddler-link-foreground: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-primary}} value="70" /> 77 | site-title-foreground: #b2b2b2 78 | static-alert-foreground: #B48EAD 79 | tab-background-selected: {{{ [colour[primary]lightness[28]alpha[0.75]] }}} 80 | tab-background: transparent 81 | tab-border-selected: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-primary}} value="60" /> 82 | tab-border: #585858 83 | tab-divider: #585858 84 | tab-foreground-selected: <$macrocall $name="color-autocontrast" color=<> /> 85 | tab-foreground: <> 86 | table-border: #535353 87 | table-footer-background: <> 88 | table-header-background: <> 89 | tag-background: <$macrocall $name="color-lightness" color={{$:/themes/cdr/captivate/settings/color-secondary}} value="range(30,85)" /> 90 | tag-foreground: <$macrocall $name="color-autocontrast" color=<> /> 91 | tiddler-background: <> 92 | tiddler-border: <> 93 | tiddler-controls-foreground-hover: #d0d0d0 94 | tiddler-controls-foreground-selected: #c0c0c0 95 | tiddler-controls-foreground: {{{ [colour[background]lightness[+36]]}}} 96 | tiddler-editor-background: #121212 97 | tiddler-editor-border-image: 98 | tiddler-editor-border: <$macrocall $name="color-mix" color1=<> color2="#f0f0f0" weight="0.3" /> 99 | tiddler-editor-fields-even: rgba(255, 255, 255, 0.17) 100 | tiddler-editor-fields-odd: rgba(255, 255, 255, 0.09) 101 | tiddler-info-background: <$macrocall $name="color-mix" color1=<> color2="#808080" weight="0.13" /> 102 | tiddler-info-border: <> 103 | tiddler-info-tab-background: <> 104 | tiddler-link-background: <> 105 | tiddler-link-foreground: {{{ [{$:/themes/cdr/captivate/settings/color-link}lightness{$:/themes/cdr/captivate/settings/text-on-dark}] }}} 106 | tiddler-subtitle-foreground: #bababa 107 | tiddler-title-foreground: <> 108 | toolbar-new-button: 109 | toolbar-options-button: 110 | toolbar-save-button: 111 | toolbar-info-button: 112 | toolbar-edit-button: 113 | toolbar-close-button: 114 | toolbar-delete-button: 115 | toolbar-cancel-button: 116 | toolbar-done-button: 117 | untagged-background: <> 118 | very-muted-foreground: #808080 119 | -------------------------------------------------------------------------------- /themes/cdr/captivate/tweaks/colors.tid: -------------------------------------------------------------------------------- 1 | type: text/vnd.tiddlywiki 2 | title: $:/themes/cdr/captivate/tweaks/colors 3 | tags: 4 | 5 | \define paletteName(theme:CaptivateLight) $:/themes/cdr/captivate/palettes/$theme$ 6 | 7 | \define circleCSS() 8 | background: $(evaled)$; 9 | width: 26px; 10 | height: 26px; 11 | border: 1px solid #a0a0a0; 12 | border-radius: 13px; 13 | display: inline-block; 14 | margin-right: 10px; 15 | \end 16 | 17 | \define colorSwatch(color) 18 | <$set name="evaled" value=<> > 19 |
>/> 20 | 21 | \end 22 | 23 | \define showCurrentColorScheme() 24 | <$macrocall $name="colorSwatch" color={{$:/themes/cdr/captivate/settings/color-primary}}/> 25 | <$macrocall $name="colorSwatch" color={{$:/themes/cdr/captivate/settings/color-secondary}}/> 26 | <$macrocall $name="colorSwatch" color={{$:/themes/cdr/captivate/settings/color-link}}/> 27 | \end 28 | 29 | \define test-default(arg:{{{[[$:/palette]get[origin]else{$:/palette}]}}}) 30 | arg = $arg$
31 | \end 32 | 33 | \define colour(name) 34 | <$transclude tiddler="$:/themes/cdr/captivate" subtiddler="$(palette)$" index="$name$"><$transclude tiddler="$:/palettes/Vanilla" index="$name$"><$transclude tiddler="$:/config/DefaultColourMappings/$name$"/> 35 | \end 36 | 37 | \define action-parse-palette(src:"" dest:"""$:/state/current-palette""") 38 | <$action-setfield $tiddler="""$:/temp/source-palette""" $value="$src$" /> 39 | <$action-setfield $tiddler="""$:/temp/source-palette""" $field=primary $value={{$:/themes/cdr/captivate/settings/color-primary}} /> 40 | <$list filter="[[$(palette)$]indexes[]sort[title]]" variable="colorName"> 41 | <$wikify name="colorValue" text={{{ [[$(palette)$]getindex] }}} mode="inline" output="text" > 42 | <$action-setfield $tiddler="""$dest$""" $index=<> $value=<> /> 43 | 44 | 45 | 46 | \end 47 | 48 | \define setColorScheme(name c1 c2 c3) 49 | <$button class="tc-btn-invisible" style="text-align: left;"> <$text text="""$name$""" /> 50 | <$action-setfield $tiddler="$:/themes/cdr/captivate/settings/color-primary" $value="$c1$"/> 51 | <$action-setfield $tiddler="$:/themes/cdr/captivate/settings/color-secondary" $value="$c2$"/> 52 | <$action-setfield $tiddler="$:/themes/cdr/captivate/settings/color-link" $value="$c3$"/> 53 | 54 | <$action-wikifypalette 55 | palette="$:/themes/cdr/captivate/palettes/CaptivateLight" 56 | save="$:/palettes/CaptivateLight" /> 57 | <$action-wikifypalette 58 | palette="$:/themes/cdr/captivate/palettes/CaptivateDark" 59 | save="$:/palettes/CaptivateDark" /> 60 | <$action-wikifypalette 61 | palette="$:/themes/cdr/captivate/palettes/CaptivateTan" 62 | save="$:/palettes/CaptivateTan" /> 63 | <$action-setfield $tiddler="$:/palette" text={{{ [{$:/themes/cdr/captivate/settings/palette-theme}sentencecase[]addprefix[$:/palettes/Captivate]] }}} /> 64 | 65 |
66 | <$macrocall $name="colorSwatch" color="$c1$"/> 67 | <$macrocall $name="colorSwatch" color="$c2$"/> 68 | <$macrocall $name="colorSwatch" color="$c3$"/> 69 |
70 | 71 | \end 72 | 73 | \define listColorSchemes() 74 | <> 75 | <> 76 | <> 77 | <> 78 | <> 79 | <> 80 | <> 81 | <> 82 | <> 83 | <> 84 | <> 85 | <> 86 | <$list filter="[all[shadows+tiddlers]tag[$:/tags/ColorScheme]sort[name]]"> 87 | <$macrocall $name="setColorScheme" name={{!!name}} c1={{##color1}} c2={{##color2}} c3={{##color3}}/> 88 | 89 | \end 90 | 91 | \define editColor(index label description) 92 | 93 | <$edit-text tiddler="$(tempTid)$" field=$index$ tag="input" type="color" default="#00aa00"/> 94 | $description$ 95 | \end 96 | 97 | \define initTempScheme() 98 | <$action-createtiddler $basetitle="$:/temp/new-color-scheme" $overwrite="yes" 99 | color1={{$:/themes/cdr/captivate/settings/color-primary}} 100 | color2={{$:/themes/cdr/captivate/settings/color-secondary}} 101 | color3={{$:/themes/cdr/captivate/settings/color-link}} 102 | name=""> 103 | \end 104 | 105 | \define newColorScheme() 106 | <$set name=schemeTiddler value="$:/snippets/colorschemes/$(schemeName)$"> 107 | <$action-createtiddler $basetitle=<> $overwrite="yes" 108 | type="application/x-tiddler-dictionary" tags="$:/tags/ColorScheme" name=<>/> 109 | <$action-setfield $tiddler=<> name=<> tags="$:/tags/ColorScheme"/> 110 | <$action-setfield $tiddler=<> $index="color1" $value={{{ [get[color1]]}}}/> 111 | <$action-setfield $tiddler=<> $index="color2" $value={{{ [get[color2]]}}}/> 112 | <$action-setfield $tiddler=<> $index="color3" $value={{{ [get[color3]]}}}/> 113 | <$action-setfield $tiddler="$:/state/edit/CaptivatePalette" $value="no"> 114 | <$action-deletetiddler $tiddler="$(tempTid)$" /> 115 | 116 | \end 117 | 118 | \define setCaptivatePalette(theme) 119 | <$action-setfield $tiddler="$:/palette" text=<> /> 120 | \end 121 | 122 |
123 | <$radio tiddler="$:/themes/cdr/captivate/settings/palette-theme" field="text" value="light" 124 | actions="""<$action-setfield $tiddler="$:/palette" text="$:/palettes/CaptivateLight"/>"""> 125 | Light Theme
126 | <$radio tiddler="$:/themes/cdr/captivate/settings/palette-theme" field="text" value="dark" 127 | actions="""<$action-setfield $tiddler="$:/palette" text="$:/palettes/CaptivateDark"/>"""> 128 | Dark Theme
129 | <$radio tiddler="$:/themes/cdr/captivate/settings/palette-theme" field="text" value="tan" 130 | actions="""<$action-setfield $tiddler="$:/palette" text="$:/palettes/CaptivateTan"/>"""> 131 | Tan  132 |
133 |
134 | <$checkbox tiddler="$:/themes/cdr/captivate/settings/accent-topbar" field="text" checked="yes" unchecked="no" 135 | default="yes" > 136 | Accent Top Bar 137 | 138 |
139 |
140 | <> 141 | <$button popup=<>> 142 | Color Schemes{{$:/core/images/down-arrow}} 143 |   144 | <$reveal state="$:/state/edit/CaptivatePalette" type="nomatch" text="yes"> 145 | <$button set="$:/state/edit/CaptivatePalette" setTo="yes" actions=<>>{{$:/core/images/edit-button}} 146 | 147 |
148 | 149 | <$reveal state=<> type="popup" position="below" animate="yes"> 150 |
151 | <> 152 |
153 | 154 | 155 | <$reveal state="$:/state/edit/CaptivatePalette" type="match" text="yes"> 156 |
157 | <$set name=tempTid value="$:/temp/new-color-scheme"> 158 | <> 159 | <> 160 | <> 161 | 162 | <$edit-text tiddler=<> field="name" tag="input" size="25" placeholder="name for your color scheme" default=""/> 163 | <>
164 |
165 | <$button class="cv-secondary-btn" set="$:/state/edit/CaptivatePalette" setTo="no">Cancel 166 |    167 | <$set name=schemeName value={{{ [get[name]] }}} > 168 | <$button actions=<> disabled={{{ [get[name]then[no]else[yes]] }}}>Create 169 | 170 |
171 | 172 |
173 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/lib/parse.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/lib/parse.js 3 | type: application/javascript 4 | module-type: library 5 | 6 | Parses a css color specification 7 | 8 | \*/ 9 | (function() { 10 | 11 | /*jslint node: true, browser: true */ 12 | /*global $tw: false */ 13 | 14 | "use strict"; 15 | 16 | // https://www.w3.org/TR/css-color-4/#named-colors 17 | var NamedColors = { 18 | "aliceblue": [240,248,255], "antiquewhite": [250,235,215], 19 | "aqua": [0,255,255], "aquamarine": [127,255,212], 20 | "azure": [240,255,255], "beige": [245,245,220], 21 | "bisque": [255,228,196], "black": [0,0,0], 22 | "blanchedalmond": [255,235,205], "blue": [0,0,255], 23 | "blueviolet": [138,43,226], "brown": [165,42,42], 24 | "burlywood": [222,184,135], "cadetblue": [95,158,160], 25 | "chartreuse": [127,255,0], "chocolate": [210,105,30], 26 | "coral": [255,127,80], "cornflowerblue": [100,149,237], 27 | "cornsilk": [255,248,220], "crimson": [220,20,60], 28 | "cyan": [0,255,255], "darkblue": [0,0,139], 29 | "darkcyan": [0,139,139], "darkgoldenrod": [184,134,11], 30 | "darkgray": [169,169,169], "darkgreen": [0,100,0], 31 | "darkgrey": [169,169,169], "darkkhaki": [189,183,107], 32 | "darkmagenta": [139,0,139], "darkolivegreen": [85,107,47], 33 | "darkorange": [255,140,0], "darkorchid": [153,50,204], 34 | "darkred": [139,0,0], "darksalmon": [233,150,122], 35 | "darkseagreen": [143,188,143], "darkslateblue": [72,61,139], 36 | "darkslategray": [47,79,79], "darkslategrey": [47,79,79], 37 | "darkturquoise": [0,206,209], "darkviolet": [148,0,211], 38 | "deeppink": [255,20,147], "deepskyblue": [0,191,255], 39 | "dimgray": [105,105,105], "dimgrey": [105,105,105], 40 | "dodgerblue": [30,144,255], "firebrick": [178,34,34], 41 | "floralwhite": [255,250,240], "forestgreen": [34,139,34], 42 | "fuchsia": [255,0,255], "gainsboro": [220,220,220], 43 | "ghostwhite": [248,248,255], "gold": [255,215,0], 44 | "goldenrod": [218,165,32], "gray": [128,128,128], 45 | "green": [0,128,0], "greenyellow": [173,255,47], 46 | "grey": [128,128,128], "honeydew": [240,255,240], 47 | "hotpink": [255,105,180], "indianred": [205,92,92], 48 | "indigo": [75,0,130], "ivory": [255,255,240], 49 | "khaki": [240,230,140], "lavender": [230,230,250], 50 | "lavenderblush": [255,240,245], "lawngreen": [124,252,0], 51 | "lemonchiffon": [255,250,205], "lightblue": [173,216,230], 52 | "lightcoral": [240,128,128], "lightcyan": [224,255,255], 53 | "lightgoldenrodyellow": [250,250,210], "lightgray": [211,211,211], 54 | "lightgreen": [144,238,144], "lightgrey": [211,211,211], 55 | "lightpink": [255,182,193], "lightsalmon": [255,160,122], 56 | "lightseagreen": [32,178,170], "lightskyblue": [135,206,250], 57 | "lightslategray": [119,136,153], "lightslategrey": [119,136,153], 58 | "lightsteelblue": [176,196,222], "lightyellow": [255,255,224], 59 | "lime": [0,255,0], "limegreen": [50,205,50], 60 | "linen": [250,240,230], "magenta": [255,0,255], 61 | "maroon": [128,0,0], "mediumaquamarine": [102,205,170], 62 | "mediumblue": [0,0,205], "mediumorchid": [186,85,211], 63 | "mediumpurple": [147,112,219], "mediumseagreen": [60,179,113], 64 | "mediumslateblue": [123,104,238], "mediumspringgreen": [0,250,154], 65 | "mediumturquoise": [72,209,204], "mediumvioletred": [199,21,133], 66 | "midnightblue": [25,25,112], "mintcream": [245,255,250], 67 | "mistyrose": [255,228,225], "moccasin": [255,228,181], 68 | "navajowhite": [255,222,173], "navy": [0,0,128], 69 | "oldlace": [253,245,230], "olive": [128,128,0], 70 | "olivedrab": [107,142,35], "orange": [255,165,0], 71 | "orangered": [255,69,0], "orchid": [218,112,214], 72 | "palegoldenrod": [238,232,170], "palegreen": [152,251,152], 73 | "paleturquoise": [175,238,238], "palevioletred": [219,112,147], 74 | "papayawhip": [255,239,213], "peachpuff": [255,218,185], 75 | "peru": [205,133,63], "pink": [255,192,203], 76 | "plum": [221,160,221], "powderblue": [176,224,230], 77 | "purple": [128,0,128], "rebeccapurple": [102,51,153], 78 | "red": [255,0,0], "rosybrown": [188,143,143], 79 | "royalblue": [65,105,225], "saddlebrown": [139,69,19], 80 | "salmon": [250,128,114], "sandybrown": [244,164,96], 81 | "seagreen": [46,139,87], "seashell": [255,245,238], 82 | "sienna": [160,82,45], "silver": [192,192,192], 83 | "skyblue": [135,206,235], "slateblue": [106,90,205], 84 | "slategray": [112,128,144], "slategrey": [112,128,144], 85 | "snow": [255,250,250], "springgreen": [0,255,127], 86 | "steelblue": [70,130,180], "tan": [210,180,140], 87 | "teal": [0,128,128], "thistle": [216,191,216], 88 | "tomato": [255,99,71], "turquoise": [64,224,208], 89 | "violet": [238,130,238], "wheat": [245,222,179], 90 | "white": [255,255,255], "whitesmoke": [245,245,245], 91 | "yellow": [255,255,0], "yellowgreen": [154,205,50] 92 | }; 93 | 94 | var Numeric = "([-+]?(?:0|[1-9]\\d*|(?=\\.\\d+))(?:\\.\\d*)?(?:[eE][-+]?\\d+)?)"; 95 | var NumberUnit = new RegExp("^"+Numeric+"([a-z%]*)$"); 96 | 97 | /* 98 | * Arguments to color functions may be separated by either spaces or commas. 99 | * Alpha channel specified after " / " takes precedence over alpha component in 100 | * a color tuple. 101 | * 102 | * Returns either: 103 | * 1) an rgb array with components in [0..255], or 104 | * 2) an object with space, coords, and alpha properties, or 105 | * 3) null 106 | */ 107 | module.exports = function parseColorString(str) { 108 | if (typeof str !== "string" && ! (str instanceof String)) { 109 | return null; 110 | } 111 | 112 | str = str.trim().toLowerCase(); 113 | 114 | if (str === "transparent") { 115 | return {space:"rgb",coords:[0,0,0],alpha:0}; 116 | } 117 | 118 | if (NamedColors.hasOwnProperty(str)) { 119 | return NamedColors[str]; 120 | } 121 | 122 | if (str[0] === "#") { 123 | return parseHex(str); 124 | } 125 | 126 | var re = /^([a-z]+)\(([^)]+)\)$/; 127 | var m = str.match(re); 128 | 129 | if (!m) { 130 | return null; 131 | } 132 | 133 | var alpha = 1; 134 | var isColorFn = (m[1] === "color"); 135 | var coords = m[2].trim().split(/\s*,\s*|\s+/); 136 | var func = (isColorFn ? coords.shift() : m[1]); 137 | 138 | var i = coords.indexOf("/"); 139 | if (i >= 0) { 140 | if (coords.length <= i+1) { 141 | return null; 142 | } 143 | var alphaStr = coords[i+1]; 144 | coords.splice(i); 145 | alpha = parseNumberOrPercent(alphaStr); 146 | } else if (coords.length > 3) { 147 | alpha = parseNumberOrPercent(coords[3]); 148 | } 149 | 150 | if (alpha === undefined) { 151 | return null; 152 | } 153 | 154 | // per css4 color() spec: 155 | // If more s or s are provided than parameters that the 156 | // color space takes, the excess s at the end are ignored. 157 | // If fewer s or s are provided than parameters that the 158 | // color space takes, the missing parameters default to 0. 159 | coords.splice(3); 160 | if (coords.length < 3) { 161 | if (! isColorFn) { 162 | return null; 163 | } 164 | // pad missing entries with 0 165 | for (var i = 3 - coords.length; i > 0; i--) { 166 | coords.push("0"); 167 | } 168 | } 169 | var space; 170 | 171 | switch(func) { 172 | case "rgb": 173 | case "rgba": 174 | space = "rgb"; 175 | coords = parseCoordsRGB(coords,255); 176 | break; 177 | case "hsl": 178 | case "hsla": 179 | space = "hsl"; 180 | coords = parseCoordsHSL(coords); 181 | break; 182 | case "display-p3": 183 | space = "p3"; 184 | coords = parseCoordsRGB(coords); 185 | break; 186 | case "lab": 187 | space = "lab"; 188 | coords = parseCoordsLab(coords); 189 | break; 190 | case "srgb": 191 | space = "rgb"; 192 | coords = parseCoordsRGB(coords); 193 | break; 194 | default: 195 | return null; 196 | } 197 | 198 | if (coords === null) { 199 | return null; 200 | } 201 | return { space:space, coords:coords, alpha:alpha }; 202 | } 203 | 204 | // convert percentage to float; if str is a number and scale is provided, return 205 | // the number divided by the scale. 206 | function parseNumberOrPercent(str,scale) { 207 | if (str === "none") return NaN; 208 | 209 | var m = str.match(NumberUnit); 210 | if (!m) { 211 | return undefined; 212 | } 213 | if (m[2] === "%") { 214 | return parseFloat(m[1]/100); 215 | } 216 | var n = parseFloat(m[1]); 217 | if (scale !== void(0) && scale > 0) { 218 | n = n / scale; 219 | } 220 | return n; 221 | } 222 | 223 | function parseNumber(str) { 224 | if (str === "none") return NaN; 225 | 226 | var m = str.match(NumberUnit); 227 | if (!m || m[2] !== "") { 228 | return undefined; 229 | } 230 | 231 | return parseFloat(m[1]); 232 | } 233 | 234 | // returns hue in degrees 235 | function parseHue(str) { 236 | if (str === "none") return NaN; 237 | 238 | var m = str.match(NumberUnit); 239 | if (!m) { 240 | return undefined; 241 | } 242 | var n = parseFloat(m[1]); 243 | 244 | switch(m[2]) { 245 | case "": 246 | case "deg": 247 | break; 248 | case "rad": 249 | n = n * 180 / Math.PI; 250 | break; 251 | case "grad": // 400 gradians in a circle 252 | n = n * 360 / 400; 253 | break; 254 | case "turn": // 1 turn in a circle 255 | n = n * 360; 256 | break; 257 | default: 258 | return undefined; 259 | } 260 | return n; 261 | } 262 | 263 | function parsePercent(str) { 264 | if (str === "none") return NaN; 265 | 266 | var m = str.match(NumberUnit); 267 | if (!m || m[2] !== "%") { 268 | return undefined; 269 | } 270 | return parseFloat(m[1])/100; 271 | } 272 | 273 | // assumes the first character is "#" 274 | function parseHex(str) { 275 | if (str === "none") return NaN; 276 | 277 | // #RGB[A] and #RRGGBB[AA] syntax. 278 | if (isNaN("0x"+str.slice(1))) { 279 | return undefined; 280 | } 281 | if (str.length === 4 || str.length === 5) { 282 | var iv = parseInt((str+"f").slice(1,5),16); 283 | return [((iv & 0xf000) >> 8) | ((iv & 0xf000) >> 12), 284 | (iv & 0xf00) >> 4| ((iv & 0xf00) >> 8), 285 | (iv & 0xf0) | ((iv & 0xf0) >> 4), 286 | ((iv & 0xf) | ((iv & 0xf) << 4)) / 255]; 287 | } else if (str.length === 7 || str.length === 9) { 288 | var iv = parseInt((str+"ff").slice(1,9),16); 289 | return [(iv & 0xff000000) >>> 24, 290 | (iv & 0xff0000) >> 16, 291 | (iv & 0xff00) >> 8, 292 | (iv & 0xff) / 255]; 293 | } 294 | 295 | return undefined; 296 | } 297 | 298 | // Numbers are interpreted from [0..scale] or [0..1] by default. 299 | function parseCoordsRGB(coords,scale) { 300 | for (var i = 0; i < 3; i++) { 301 | coords[i] = parseNumberOrPercent(coords[i],scale); 302 | if (coords[i] === undefined) { 303 | return null; 304 | } 305 | } 306 | return coords; 307 | } 308 | 309 | // Adapted from https://www.w3.org/TR/css-color-4/#hsl-to-rgb 310 | // Returns RGB components in [0..1] 311 | function parseCoordsHSL(coords) { 312 | var hsl = [ 313 | parseHue(coords[0]), 314 | parsePercent(coords[1]), 315 | parsePercent(coords[2]) 316 | ]; 317 | 318 | if (hsl.includes(undefined)) { 319 | return null; 320 | } 321 | 322 | return hsl; 323 | } 324 | 325 | function parseCoordsLab(coords) { 326 | var lab = [ 327 | parsePercent(coords[0]) * 100, 328 | parseNumber(coords[1]), 329 | parseNumber(coords[2]) 330 | ]; 331 | 332 | if (lab.includes(undefined)) { 333 | return null; 334 | } 335 | 336 | return lab; 337 | } 338 | 339 | })(); 340 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/lib/color.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/lib/color.js 3 | type: application/javascript 4 | module-type: library 5 | 6 | Color manipulation library 7 | 8 | \*/ 9 | (function() { 10 | 11 | /*jslint node: true, browser: true */ 12 | /*global $tw: false */ 13 | "use strict"; 14 | 15 | var Convert = require("$:/plugins/cdr/colorlab/lib/convert.js"); 16 | var parseColorString = require("$:/plugins/cdr/colorlab/lib/parse.js"); 17 | 18 | if (!Array.isArray) { 19 | Array.isArray = function (arg) { 20 | return Object.prototype.toString.call(arg) === '[object Array]'; 21 | }; 22 | } 23 | 24 | function clone(obj) { 25 | return JSON.parse(JSON.stringify(obj)); 26 | } 27 | 28 | /* 29 | Create a Color object. If unable to process the input, rgba(0,0,0,0) is 30 | created. 31 | 32 | Valid inputs are: 33 | - CSS color string 34 | - object: {space, coords, alpha} 35 | - array with [0..255] rgb values and optional alpha in [0..1] 36 | - multiple arguments: space, coords, [alpha] 37 | */ 38 | function Color(color,optCoords,optAlpha) { 39 | // If we are called as a function, call using new instead 40 | if (!(this instanceof Color)) { 41 | return new Color(color,optCoords,optAlpha); 42 | } 43 | 44 | var alpha = 1; 45 | 46 | Object.defineProperty(this,'alpha',{ 47 | get: function() { return alpha;}, 48 | set: function(a) { alpha = Convert.clamp(a,0,1); } 49 | }); 50 | 51 | // If input is already a Color, return a copy of itself 52 | if (color instanceof Color) { 53 | this.space = color.space; 54 | this.coords = color.coords.slice(0); 55 | this.alpha = color.alpha; 56 | return; 57 | } 58 | 59 | if (typeof color === "string" || color instanceof String) { 60 | color = parseColorString(color); 61 | } 62 | 63 | // If input is an array, assumes it contains rgb tuple in [0..255] 64 | if (Array.isArray(color) && color.length >= 3) { 65 | setupInternal.call(this,"rgb", 66 | color.slice(0,3).map(function(e) {return e/255;}), 67 | color.length > 3 ? color[3] : 1) 68 | } else if (color && typeof color === "object" && color.space) { 69 | setupInternal.call(this,color.space,color.coords,color.alpha); 70 | } else if (arguments.length >= 2 && Array.isArray(arguments[1])) { 71 | setupInternal.call(this,arguments[0],arguments[1],arguments[2]); 72 | } else { 73 | setupInternal.call(this,"rgb",[0,0,0],0); 74 | } 75 | } 76 | 77 | /* 78 | For each color space, set up getter and setter to the coords of the 79 | given space. Example: 80 | 81 | coords = color.rgb; // returns coords in rgb color space 82 | color.lab = coords; // changes the color by using the coords in lab space 83 | */ 84 | Object.keys(Convert.spaces).forEach(function(id) { 85 | Object.defineProperty(Color.prototype,id,{ 86 | get: function() { 87 | return convert(this.space,this.coords,id); 88 | }, 89 | set: function(coords) { // e.g. color.lch = coords 90 | coords = coords.slice(0); 91 | Convert.getSpace(id).clip(coords); 92 | this.coords = convert(id,coords,this.space); 93 | } 94 | }) 95 | },this); 96 | 97 | function setupInternal(space,coords,alpha) { 98 | if (Convert.spaces.hasOwnProperty(space)) { 99 | this.space = space; 100 | this.coords = coords.slice(0); 101 | this.alpha = alpha == null ? 1 : alpha; 102 | Convert.getSpace(this.space).clip(this.coords); 103 | } else { 104 | throw new Error('unknown color space ' + color.space); 105 | } 106 | } 107 | 108 | /** 109 | * If value is given (will be clipped between [0..100]), sets the lightness 110 | * level to the specified value. Otherwise, returns current lightness level. 111 | */ 112 | Object.defineProperty(Color.prototype,'lightness',{ 113 | get: function() { 114 | return (this.lch)[0]; 115 | }, 116 | set: function(value) { 117 | var lch = this.lch; 118 | var lightness = lch[0]; 119 | 120 | value = Convert.clamp(value,0,100); 121 | // When a color has high lightness, it's chroma is typically clipped 122 | // to fit in rgb, so decreasing L tends to introduce black shade; 123 | // try to compensate by increasing chroma first 124 | if (value < lightness && lightness >= 80 && lch[1] > 0.5) { 125 | //var adjust = 100 - 0.04 * Math.pow(50-value, 2); 126 | lch[1] += Math.max(20 - 0.008 * Math.pow(50-value,2),2); 127 | } 128 | lch[0] = value; 129 | this.lch = lch; 130 | } 131 | }) 132 | 133 | /** 134 | * Convert to color space and return a new color 135 | */ 136 | Color.prototype.to = function(spaceId) { 137 | return new Color({ 138 | space: spaceId, 139 | coords: this[spaceId], 140 | alpha: this.alpha 141 | }); 142 | } 143 | 144 | Color.prototype.toString = function(space) { 145 | if (space !== void(0) && !(Convert.spaces.hasOwnProperty(space))) { 146 | throw new Error('unknown color space ' + space); 147 | } 148 | if (space === void(0)) { 149 | space = this.space; 150 | } 151 | var tuple; 152 | if (space === this.space) { 153 | tuple = this.coords; 154 | } else { 155 | tuple = this[space]; 156 | } 157 | return Convert.spaces[space].toString(tuple,this.alpha); 158 | }; 159 | 160 | Color.prototype.mixSRLAB2 = function(colorB,weight) { 161 | if (!(colorB instanceof Color)) { 162 | throw new TypeError('Input must be of type Color.'); 163 | } 164 | 165 | var colorA = this; 166 | var labA = colorA.srlab2; 167 | var labB = colorB.srlab2; 168 | 169 | if(colorA.alpha < 1) { 170 | premultiply("srlab2",labA,colorA.alpha); 171 | } 172 | if(colorB.alpha < 1) { 173 | premultiply("srlab2",labB,colorB.alpha); 174 | } 175 | 176 | weight = Convert.clamp(weight,0,1); 177 | 178 | var l = labA[0] + weight * (labB[0] - labA[0]); 179 | var a = labA[1] + weight * (labB[1] - labA[1]); 180 | var b = labA[2] + weight * (labB[2] - labA[2]); 181 | 182 | var alpha = colorA.alpha + weight * (colorB.alpha - colorA.alpha); 183 | if (alpha !== 0) { 184 | l = l / alpha; 185 | a = a / alpha; 186 | b = b / alpha; 187 | } 188 | 189 | return (new Color({space: "srlab2",coords:[l,a,b],alpha:alpha})).to(this.space); 190 | } 191 | 192 | Color.prototype.mixXYZ = function(colorB,weight) { 193 | if (!(colorB instanceof Color)) { 194 | throw new TypeError('Input must be of type Color.'); 195 | } 196 | 197 | var colorA = this; 198 | var xyzA = colorA.xyz; 199 | var xyzB = colorB.xyz; 200 | 201 | if(colorA.alpha < 1) { 202 | premultiply("xyz",xyzA,colorA.alpha); 203 | } 204 | if(colorB.alpha < 1) { 205 | premultiply("xyz",xyzB,colorB.alpha); 206 | } 207 | 208 | weight = Convert.clamp(weight,0,1); 209 | 210 | var x = xyzA[0] + weight * (xyzB[0] - xyzA[0]); 211 | var y = xyzA[1] + weight * (xyzB[1] - xyzA[1]); 212 | var z = xyzA[2] + weight * (xyzB[2] - xyzA[2]); 213 | 214 | var alpha = colorA.alpha + weight * (colorB.alpha - colorA.alpha); 215 | if (alpha !== 0) { 216 | x = x / alpha; 217 | y = y / alpha; 218 | z = z / alpha; 219 | } 220 | 221 | return (new Color({space: "xyz",coords:[x,y,z],alpha:alpha})).to(this.space); 222 | } 223 | 224 | Color.prototype.mix = Color.prototype.mixSRLAB2; 225 | 226 | // returns alpha composite color (this over colorB) using the "source over" operator 227 | Color.prototype.over = function(colorB) { 228 | if (!(colorB instanceof Color)) { 229 | throw new TypeError('Input must be of type Color.'); 230 | } 231 | 232 | if(this.alpha === 1) { 233 | return (new Color(this)); 234 | } 235 | if(this.alpha === 0) { 236 | return (new Color(colorB)); 237 | } 238 | var rgbA = this.rgb, rgbB = colorB.rgb; 239 | 240 | premultiply("rgb",rgbA,this.alpha); 241 | premultiply("rgb",rgbB,colorB.alpha); 242 | 243 | var r = rgbA[0] + rgbB[0] * (1 - this.alpha), 244 | g = rgbA[1] + rgbB[1] * (1 - this.alpha), 245 | b = rgbA[2] + rgbB[2] * (1 - this.alpha), 246 | alpha = this.alpha + colorB.alpha * (1 - this.alpha); 247 | 248 | r /= alpha; 249 | g /= alpha; 250 | b /= alpha; 251 | return (new Color({space:"rgb",coords:[r,g,b],alpha:alpha})); 252 | } 253 | 254 | // returns the relative luminance of the color--"Y" component of the xyz space 255 | Color.prototype.luminance = function() { 256 | var xyz = this.xyz; 257 | return xyz[1]; 258 | } 259 | 260 | // returns the contrast ratio between two colors 261 | Color.prototype.contrast = function(color) { 262 | if (!(color instanceof Color)) { 263 | throw new TypeError('Input must be of type Color.'); 264 | } 265 | 266 | var L1 = this.luminance(), 267 | L2 = color.luminance(); 268 | 269 | if (L2 > L1) { 270 | var temp = L1; 271 | var L1 = L2; 272 | var L2 = temp; 273 | } 274 | 275 | return (L1 + .05) / (L2 + .05); 276 | } 277 | 278 | // deltaE2000 - http://www2.ece.rochester.edu/~gsharma/ciede2000/ 279 | Color.prototype.deltaE = function(color,konst) { 280 | var lab1 = this.lab, 281 | lab2 = color.lab; 282 | 283 | return deltaE(lab1,lab2,konst); 284 | } 285 | 286 | Color.parse = parseColorString; 287 | 288 | // multiply (in place) any non-angle coordinate by alpha value 289 | function premultiply(space,coords,alpha) { 290 | space = Convert.getSpace(space); 291 | coords.forEach(function(c,i,coords) { 292 | if (! space.coords[i].isAngle) { 293 | coords[i] *= alpha; 294 | } 295 | }); 296 | } 297 | 298 | // map coords to new space, force the gamut if necessary 299 | function convert(fromSpaceID,coords,toSpaceID) { 300 | var fromSpace = Convert.getSpace(fromSpaceID); 301 | var toSpace = Convert.getSpace(toSpaceID); 302 | 303 | var temp = Convert.map(fromSpace,coords,toSpace); 304 | 305 | if (!Convert.isInSpace(toSpace,temp) && toSpace.intoGamut) { 306 | temp = forceIntoGamut(fromSpace,coords,toSpace) 307 | } 308 | return temp; 309 | } 310 | 311 | function forceIntoGamut(fromSpace,coords,toSpace) { 312 | var lchSpace = Convert.getSpace("lchsr"); 313 | var lch = Convert.map(fromSpace,coords,lchSpace); 314 | 315 | var transformFromLCH = function(lch,toSpace) { 316 | return Convert.map(lchSpace,lch,toSpace) 317 | } 318 | 319 | var temp; 320 | var hiC = lch[1]; 321 | var loC = 0; 322 | var ε = 0.0005; 323 | 324 | temp = transformFromLCH(lch,toSpace); 325 | 326 | lch[1] /= 2; 327 | 328 | // .0001 chosen fairly arbitrarily as "close enough" 329 | while (hiC - loC > ε) { 330 | temp = transformFromLCH(lch,toSpace); 331 | 332 | if (Convert.isInSpace(toSpace,temp)) { 333 | loC = lch[1]; 334 | } else { 335 | hiC = lch[1]; 336 | } 337 | lch[1] = (hiC + loC)/2; 338 | } 339 | 340 | toSpace.clip(temp); 341 | return temp; 342 | } 343 | 344 | function deltaE(lab1,lab2,konst) { 345 | var kL = 1,kC = 1,kH = 1; 346 | if (konst !== void(0)) { 347 | kL = konst[0]; 348 | kC = konst[1]; 349 | kH = konst[2]; 350 | } 351 | var chroma1 = Math.sqrt(lab1[1]*lab1[1] + lab1[2]*lab1[2]), 352 | chroma2 = Math.sqrt(lab2[1]*lab2[1] + lab2[2]*lab2[2]); 353 | var Lavg = (lab1[0] + lab2[0]) / 2, 354 | C7 = Math.pow(0.5 * (chroma1 + chroma2),7), 355 | d2r = 0.017453292519943295,// Math.PI/180, 356 | P25 = 6103515625,// Math.pow(25,7), 357 | G = 0.5 * (1 - Math.sqrt(C7/(C7 + P25))), 358 | a1 = lab1[1] * (1+G), 359 | a2 = lab2[1] * (1+G), 360 | C1 = Math.sqrt(a1 * a1 + lab1[2] * lab1[2]), 361 | C2 = Math.sqrt(a2 * a2 + lab2[2] * lab2[2]), 362 | h1 = a1 == 0 && lab1[2] == 0 ? 0 : Convert.clamp360(Math.atan2(lab1[2],a1)/d2r), 363 | h2 = a2 == 0 && lab2[2] == 0 ? 0 : Convert.clamp360(Math.atan2(lab2[2],a2)/d2r), 364 | dL = lab2[0] - lab1[0], 365 | dC = C2 - C1, 366 | Cavg = (C1 + C2) / 2, 367 | dh = h2 - h1, 368 | Havg = h1 + h2; 369 | 370 | if (C1*C2 !== 0) { 371 | if (dh > 180) { 372 | dh = dh - 360; 373 | Havg = Havg < 360 ? (Havg +360) / 2 : (Havg - 360) / 2; 374 | } else if (dh < -180) { 375 | dh = dh + 360; 376 | Havg = Havg < 360 ? (Havg +360) / 2 : (Havg - 360) / 2; 377 | } else { 378 | Havg = Havg / 2; 379 | } 380 | } 381 | 382 | var dH = 2 * Math.sqrt(C1 * C2) * Math.sin(dh/2 * d2r), 383 | T = 1 384 | - 0.17 * Math.cos((Havg - 30) * d2r) 385 | + 0.24 * Math.cos((2 * Havg) * d2r) 386 | + 0.32 * Math.cos((3 * Havg + 6) * d2r) 387 | - 0.20 * Math.cos((4 * Havg - 63) * d2r), 388 | Cavg7 = Math.pow(Cavg,7), 389 | Lavg2 = Math.pow(Lavg - 50,2), 390 | RC = 2 * Math.sqrt(Cavg7/(Cavg7 + P25)), 391 | SL = 1 + (0.015 * Lavg2 / Math.sqrt(20 + Lavg2)), 392 | SC = 1 + 0.045 * Cavg, 393 | SH = 1 + 0.015 * Cavg * T, 394 | RT = - Math.sin(60 * Math.exp(-Math.pow((Havg - 275)/25,2))*d2r) * RC; 395 | 396 | var dE = Math.sqrt(Math.pow(dL/(kL * SL),2) 397 | + Math.pow(dC/(kC * SC),2) 398 | + Math.pow(dH/(kH * SH),2) 399 | + RT * dC * dH / (kC * SC * kH * SH)); 400 | 401 | return dE; 402 | } 403 | 404 | module.exports = Color; 405 | 406 | })(); 407 | 408 | //rgb [255,255,255] => xyz[0.96422, 1, 0.82521] lab[1000.00000, 0.00000, 0] lch[1000, 0, 0] 409 | -------------------------------------------------------------------------------- /themes/cdr/captivate/css/base-layout.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/css/base-layout 2 | 3 | \import [[$:/themes/cdr/captivate/ui/TopBar/Menu]] 4 | 5 | \define voffset() 56px 6 | \define fabsize() 36px 7 | \define fabgap() 10px 8 | \define fabxy() 4px 9 | 10 | .tc-dropzone > p { 11 | margin: 0px; 12 | } 13 | 14 | /* TABS */ 15 | 16 | .tc-tab-set .tc-tab-buttons:not(.tc-vertical) { 17 | margin-bottom: 0px; 18 | } 19 | 20 | .tc-tab-set .tc-tab-buttons:not(.tc-vertical) button { 21 | margin: 2px 7px 0px 0px; 22 | padding: 3px 5px; 23 | border: none; 24 | } 25 | 26 | .tc-tab-set > .tc-tab-buttons:not(.tc-vertical) button.tc-tab-selected { 27 | border-bottom: 2px solid <>; 28 | margin-bottom: -2px; 29 | } 30 | 31 | .tc-tab-set > .tc-tab-buttons.tc-vertical { 32 | padding-top: 0; 33 | margin-right: -1px; 34 | } 35 | 36 | .tc-tab-set > .tc-tab-buttons.tc-vertical > button { 37 | margin-top: 3px; 38 | margin-bottom: 3px; 39 | } 40 | 41 | .tc-tab-set > .tc-tab-buttons.tc-vertical > button { 42 | border-right: 1px solid transparent; 43 | text-align: left; 44 | } 45 | 46 | .tc-tab-set > .tc-tab-buttons.tc-vertical > button.tc-tab-selected { 47 | border-top: none; 48 | border-bottom: none; 49 | border-left: none; 50 | border-right: 2px solid <>; 51 | } 52 | 53 | .tc-tab-divider { 54 | z-index: -1; 55 | } 56 | 57 | .tc-tab-set .tc-tab-content.tc-vertical { 58 | margin-top: 0; 59 | margin-left: 0px; 60 | } 61 | 62 | .tc-tab-content .tc-search-results { 63 | display: block; 64 | overflow-y: auto; 65 | height: 50vh; 66 | } 67 | 68 | div.tc-tab-content div.tc-file-input-wrapper { 69 | margin-bottom: 0px; 70 | } 71 | 72 | .tc-tab-content.tc-sidebar-tabs-more .tc-tag-list-item { 73 | display: flex; 74 | align-items: center; 75 | margin-top: 5px; 76 | } 77 | 78 | /* VANILLA TWEAKS */ 79 | 80 | .tc-story-river { 81 | padding: 0px; 82 | padding-top: <>; 83 | } 84 | 85 | .tc-modal-wrapper { z-index: 1000; } 86 | 87 | .tc-modal-backdrop { 88 | overflow: hidden; 89 | } 90 | 91 | .tc-plugin-info-dropdown, 92 | .tc-plugin-info { 93 | border: 1px solid <>; 94 | } 95 | 96 | .tc-plugin-reload-warning { 97 | z-index: 2000; 98 | } 99 | 100 | /* TOPBAR */ 101 | 102 | .tc-adjust-top-of-scroll { 103 | position: fixed; 104 | top: 0; 105 | min-height: calc(5px + <>); 106 | max-height: calc(5px + <>); 107 | } 108 | 109 | .cv-topbar-wrapper { 110 | position: fixed; 111 | top: 0; 112 | left: 0; 113 | width: 100%; 114 | height: <>; 115 | z-index: 1000; 116 | display: flex; 117 | flex-flow: row nowrap; 118 | align-items: center; 119 | } 120 | 121 | .cv-topbar-wrapper .cv-topbar-btn, 122 | .cv-sidebar-header .cv-topbar-btn { 123 | margin: 0px 12px; 124 | } 125 | 126 | .cv-topbar-wrapper .cv-topbar-main { 127 | display: flex; 128 | width: 100%; 129 | align-items: center; 130 | } 131 | 132 | .cv-topbar-wrapper .cv-topbar-title, 133 | .cv-sidebar .cv-topbar-title { 134 | flex-grow: 1; 135 | flex-basis: 0; 136 | } 137 | 138 | .cv-topbar-main > .tc-page-controls { 139 | flex-basis: max-content; 140 | flex-shrink: 0; 141 | margin: 0px; 142 | } 143 | 144 | .cv-topbar-wrapper .tc-page-controls > .tc-popup { 145 | left: unset !important; 146 | right: 10px; 147 | } 148 | 149 | @media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 150 | .cv-topbar-wrapper .tc-page-controls { 151 | display: none; 152 | } 153 | } 154 | 155 | @media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 156 | <$list filter=<> variable="ignore"> 157 | .cv-topbar-wrapper .cv-search-bar, 158 | .cv-topbar-wrapper .tc-page-controls { 159 | display: none; 160 | } 161 | 162 | } 163 | 164 | /* SEARCHBAR */ 165 | 166 | .cv-search-bar { 167 | display: flex; 168 | margin: 0px 12px; 169 | } 170 | 171 | .cv-search-bar input { 172 | border: 0; 173 | padding: 2px 6px; 174 | margin: 0px 10px; 175 | } 176 | 177 | .cv-search-bar input:focus { 178 | width:25em; 179 | outline: 1px solid <>; 180 | } 181 | 182 | div.cv-search-dropdown { 183 | position: fixed; 184 | top: <>; 185 | right: 10px; 186 | min-width: 30%; 187 | max-width: 30%; 188 | max-height: 80vh; 189 | margin: 0px; 190 | padding: 0px; 191 | overflow-y: hidden; 192 | } 193 | 194 | .cv-search-dropdown p { 195 | margin-top: 3px; 196 | margin-bottom: 3px; 197 | } 198 | 199 | .cv-search-dropdown > .tc-tab-set > .tc-tab-buttons { 200 | display: flex; 201 | padding: 0; 202 | justify-content: space-around; 203 | } 204 | 205 | .cv-search-dropdown > .tc-tab-set > .tc-tab-buttons > button { 206 | flex-basis: 25%; 207 | margin: 0px; 208 | } 209 | 210 | .cv-search-dropdown .tc-tab-content, 211 | .cv-search-dropdown .tc-tab-content > div { 212 | width: 100%; 213 | } 214 | 215 | .cv-search-dropdown > .tc-tab-set > .tc-tab-content { 216 | padding: 0 0px 3px 8px; 217 | margin: 0; 218 | } 219 | 220 | .cv-search-dropdown .tc-tab-content .tc-search { 221 | display: none !important; 222 | } 223 | 224 | .cv-search-dropdown .tc-tab-content .tc-search-results { 225 | padding: 0px; 226 | } 227 | 228 | .tc-search-drop-down a { 229 | overflow: hidden; 230 | } 231 | 232 | /* BOTTOMBAR */ 233 | 234 | @media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 235 | .cv-bottombar-wrapper { 236 | display: none; 237 | } 238 | } 239 | 240 | .cv-bottombar-wrapper { 241 | position: fixed; 242 | width: 100%; 243 | left: 0; 244 | bottom: 0; 245 | z-index: 1000; 246 | padding-top: 0.5rem; 247 | padding-bottom: calc(12px + env(safe-area-inset-bottom)); 248 | padding-left: 16px; 249 | padding-right: 16px; 250 | } 251 | 252 | .cv-bottombar-wrapper .tc-page-controls { 253 | display: flex; 254 | flex-wrap: wrap; 255 | justify-content: space-between; 256 | align-items: center; 257 | height: 30px; 258 | margin: 0px; 259 | overflow: auto; 260 | } 261 | 262 | .cv-bottombar-wrapper .tc-page-controls button { 263 | margin-right: 0px; 264 | } 265 | 266 | /* SIDEBAR */ 267 | 268 | div.cv-sidebar { 269 | position: fixed; /* absolute works */ 270 | left: 0; 271 | top: <>; 272 | bottom: 0; 273 | z-index: 1000; 274 | overflow-x: hidden; 275 | overflow-y: hidden; 276 | } 277 | 278 | @media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 279 | div.cv-sidebar { 280 | width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}}; 281 | } 282 | } 283 | 284 | .cv-sidebar *::-webkit-scrollbar { 285 | height: 6px; 286 | width: 6px; 287 | } 288 | 289 | .cv-sidebar > .tc-sidebar-tabs { 290 | height: calc(100vh - <>); 291 | height: calc(-webkit-fill-available - <>); 292 | } 293 | 294 | .cv-sidebar .tc-tab-set.tc-sidebar-tabs-main { 295 | height: 100%; 296 | display: flex; 297 | flex-flow: column; 298 | } 299 | 300 | .cv-sidebar .tc-tab-set.tc-sidebar-tabs-main > .tc-tab-content { 301 | flex-grow: 1; 302 | height: calc(100vh - <> - 28px); 303 | height: calc(-webkit-fill-available - <> - 28px); 304 | padding: 15px 5px 15px 12px; 305 | margin: 0px; 306 | scrollbar-width: none; 307 | overflow-y: scroll; 308 | -webkit-overflow-scrolling: touch; 309 | } 310 | 311 | .cv-sidebar .tc-more-sidebar { 312 | height: calc(100vh - <> - 28px - 30px); 313 | height: calc(-webkit-fill-available - <> - 28px - 30px); 314 | } 315 | 316 | div.tc-more-sidebar > .tc-tab-set, 317 | div.tc-more-sidebar > .tc-tab-set > .tc-tab-content { 318 | height: 100%; 319 | -webkit-overflow-scrolling: touch; 320 | } 321 | 322 | .tc-sidebar-tabs-main.tc-tab-content ul { 323 | padding-left: 16px; 324 | margin: 0; 325 | } 326 | 327 | .tc-sidebar-tabs-main.tc-tab-content p { 328 | margin-top: 0px; 329 | margin-bottom: 0px; 330 | } 331 | 332 | .cv-sidebar .tc-sidebar-tabs > p:first-child { 333 | margin: 0px; 334 | } 335 | 336 | .cv-sidebar .tc-tab-buttons.tc-sidebar-tabs-main { 337 | display: flex; 338 | justify-content: space-around; 339 | padding-top: 4px; 340 | margin-left: 5px; 341 | } 342 | 343 | cv-sidebar .tc-more-sidebar { 344 | width: 100%; 345 | margin-left: -10px; 346 | } 347 | 348 | .tc-sidebar-tabs-main div[class*="tc-btn-"] { 349 | margin-bottom: 6px; 350 | } 351 | 352 | .tc-sidebar-tabs-main div[class*="tc-btn-"] button { 353 | padding: 1px 10px; 354 | } 355 | 356 | .cv-sidebar .tc-tab-content.tc-sidebar-tabs-more > div > .tc-menu-list-item, 357 | .cv-sidebar .tc-tab-content.tc-sidebar-tabs-more .tc-menu-list-item > .tc-menu-list-subitem { 358 | overflow-x: hidden; 359 | line-height: 1.2; 360 | padding: 2px 0px 2px 2px; 361 | } 362 | 363 | .cv-sidebar .tc-tab-content.tc-sidebar-tabs-more > div > .tc-menu-list-item:hover, 364 | .cv-sidebar .tc-tab-content.tc-sidebar-tabs-more .tc-menu-list-item > .tc-menu-list-subitem:hover { 365 | overflow-x: visible; 366 | height: auto; 367 | } 368 | 369 | .cv-sidebar .tc-sidebar-tabs-more .tc-tab-set .tc-menu-list-item { 370 | margin-bottom: 0.8em; 371 | } 372 | 373 | .cv-sidebar .tc-tab-content div[class^="tc-btn-"] button { 374 | border: 1px solid <>; 375 | padding: 1px 10px; 376 | min-height: 16px; 377 | margin: 0px 1px 0px 5px; 378 | } 379 | 380 | .cv-sidebar .tc-tab-content ol.tc-toc { 381 | margin-top: 0px; 382 | margin-bottom: 0px; 383 | } 384 | 385 | /* ACCENT TOPBAR: YES */ 386 | 387 | <$reveal type="nomatch" state="$:/themes/cdr/captivate/settings/accent-topbar" text="no" default="yes"> 388 | div.cv-sidebar-header { 389 | display: none; 390 | } 391 | 392 | .cv-search-bar input:not(:focus) { 393 | width:10em; 394 | } 395 | 396 | div.cv-sidebar { 397 | top: <>; 398 | height: calc(100vh - <>); 399 | } 400 | 401 | .tc-story-river { 402 | padding-top: calc(<> + 20px); 403 | } 404 | 405 | 406 | /* ACCENT TOPBAR: NO */ 407 | 408 | <$reveal type="match" state="$:/themes/cdr/captivate/settings/accent-topbar" text="no"> 409 | @media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 410 | .cv-topbar-wrapper .cv-topbar-title { 411 | visibility: hidden; 412 | } 413 | } 414 | 415 | div.cv-sidebar { 416 | top: 0px; 417 | height: 100%; 418 | } 419 | 420 | div.cv-sidebar-header { 421 | display: flex; 422 | align-items: center; 423 | height: <>; 424 | } 425 | 426 | .cv-search-bar input:not(:focus) { 427 | width:10em; 428 | } 429 | 430 | 431 | /* STORY RIVER */ 432 | 433 | @media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 434 | <$reveal type="nomatch" state="$:/state/sidebar" text="no" default={{{[subfilter{$:/themes/cdr/captivate/ui/SideBar/default}] }}} > 435 | .tc-story-river { 436 | margin-left: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}}; 437 | margin-right: unset; 438 | width: calc(100vw - {{$:/themes/tiddlywiki/vanilla/metrics/sidebarwidth}} - 30px); 439 | } 440 | 441 | <$reveal type="match" state="$:/view" text="zoomin"> 442 | body.tc-body .tc-storyview-zoomin-tiddler { 443 | width: calc(100% - 60px); 444 | } 445 | 446 | 447 | 448 | <$reveal type="match" state="$:/state/sidebar" text="no" default={{{[subfilter{$:/themes/cdr/captivate/ui/SideBar/default}] }}} > 449 | .tc-story-river { 450 | width: 100vw; 451 | } 452 | .cv-topbar-wrapper .cv-topbar-title { 453 | visibility: visible; 454 | } 455 | 456 | <$reveal type="match" state="$:/view" text="zoomin"> 457 | body.tc-body .tc-storyview-zoomin-tiddler { 458 | width: calc(100% - 42px * 10); 459 | left: calc(42px * 5); 460 | } 461 | 462 | 463 | 464 | .tc-tiddler-frame { 465 | width: 80%; 466 | width: min(80%, {{$:/themes/cdr/captivate/settings/tiddlerwidth}}); 467 | margin-left: auto; 468 | margin-right: auto; 469 | padding: 24px 48px 36px; 470 | border-radius: 8px; 471 | } 472 | } 473 | 474 | <$reveal type="match" state="$:/themes/tiddlywiki/vanilla/options/stickytitles" text="yes" default ="no"> 475 | .tc-tiddler-frame .tc-tiddler-title { 476 | top: <>; 477 | padding: 3px 0px; 478 | z-index: 700; 479 | } 480 | 481 | 482 | /* PORTRAIT */ 483 | 484 | @media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 485 | div.cv-sidebar { 486 | width: 100%; 487 | } 488 | 489 | .cv-search-bar input { 490 | display: none; 491 | } 492 | 493 | .cv-search-dropdown { 494 | left: 0; 495 | width: 100%; 496 | } 497 | 498 | .tc-drop-down, .tc-block-dropdown { 499 | font-size: 0.9rem !important; 500 | } 501 | 502 | .tc-block-dropdown.cv-search-dropdown { 503 | top: <> !important; 504 | left: 0px !important; 505 | overflow-y: hidden; 506 | max-height: calc(100vh - 56px); 507 | min-width: 100%; 508 | margin: 0px; 509 | } 510 | 511 | div.cv-search-dropdown > .tc-tab-set > .tc-tab-content { 512 | max-height: calc(100vh - 30px - 56px); 513 | overflow-y: scroll; 514 | } 515 | 516 | .cv-search-dropdown .tc-tab-buttons { 517 | z-index: 900; 518 | } 519 | 520 | .cv-fab-wrapper { 521 | display: none; 522 | } 523 | 524 | .tc-storyview-zoomin-tiddler.tc-tiddler-frame { 525 | width: 100%; 526 | padding-bottom: 50px; 527 | } 528 | 529 | .cv-bottombar-wrapper .tc-drop-down, 530 | .cv-bottombar-warpper .tc-block-dropdown { 531 | position: fixed !important; 532 | bottom: 50px !important; 533 | left: 25px; !important; 534 | max-height: calc(100% - 200px); 535 | min-width: calc(100% - 50px); 536 | max-width: calc(100% - 50px); 537 | overflow: auto; 538 | z-index: 1000; 539 | } 540 | 541 | .tc-alerts { 542 | max-width: 100%; 543 | } 544 | 545 | .tc-tiddler-frame { 546 | width: calc(100% - 16px); 547 | padding: 12px; 548 | margin: 10px auto; 549 | } 550 | 551 | .tc-story-river { 552 | top: 0px; 553 | padding: 0px; 554 | margin-top: <>; 555 | margin-bottom: <>; 556 | } 557 | } 558 | 559 | /* FAB BUTTONS */ 560 | 561 | @media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 562 | .cv-fab-wrapper { 563 | position: fixed; 564 | top: <>; 565 | right: 3px; 566 | z-index: 800; 567 | } 568 | 569 | .tc-page-controls button.cv-fab-item { 570 | margin: <>; 571 | height: <>; 572 | width: <>; 573 | padding: 0; 574 | line-height: 1; 575 | /* display: flex; */ 576 | /* align-items: center; */ 577 | /*justify-content: space-around;*/ 578 | } 579 | 580 | .cv-fab-item svg.tc-image-button { 581 | margin: 0; 582 | padding: 0; 583 | } 584 | 585 | .cv-fab-list-item { 586 | position: relative; 587 | } 588 | 589 | .cv-fab-list-item .tc-popup { 590 | top: 0px !important; 591 | right: calc(<> + <> * 2) !important; 592 | left: unset !important; 593 | } 594 | 595 | .cv-fab-list-item .tc-popup > .tc-drop-down { 596 | min-height: auto; 597 | max-height: 60vh; 598 | } 599 | 600 | .cv-fab-wrapper .tc-drop-down, 601 | .cv-fab-wrapper .tc-block-dropdown { 602 | max-height: 60vh; 603 | } 604 | } 605 | 606 | @media print { 607 | .cv-topbar-wrapper, 608 | .cv-bottombar-wrapper, 609 | .cv-sidebar, 610 | .cv-fab-wrapper { 611 | display: none !important; 612 | } 613 | 614 | .tc-story-river { 615 | margin: 0px; 616 | width: auto; 617 | padding: 0px; 618 | } 619 | 620 | .tc-story-river .tc-tiddler-frame { 621 | width: 100%; 622 | padding: 0px; 623 | margin-bottom: 18pt; 624 | box-shadow: none; 625 | page-break-inside: avoid; 626 | } 627 | } 628 | -------------------------------------------------------------------------------- /themes/cdr/captivate/css/base.tid: -------------------------------------------------------------------------------- 1 | title: $:/themes/cdr/captivate/css/base 2 | tags: $:/tags/Stylesheet 3 | list-after: $:/themes/tiddlywiki/vanilla/base 4 | 5 | \rules only filteredtranscludeinline transcludeinline macrodef macrocallinline macrocallblock html 6 | 7 | \define dur() 300ms 8 | 9 | \define outline-color() {{{ [colour[selection-background]deviate[]] }}} 10 | 11 | /* Captivate Theme CSS */ 12 | 13 | h1,h2,h3,h4,h5,h6 { font-weight: 400; } 14 | 15 | h1 { font-size: 1.5em; } 16 | h2 { font-size: 1.32em; } 17 | 18 | .tc-tiddler-body h1, .tc-tiddler-body h2, 19 | .tc-tiddler-body h3, .tc-tiddler-body h4 { 20 | margin-top: 1rem; 21 | margin-bottom: 1rem; 22 | } 23 | 24 | .tc-tiddler-body h5, .tc-tiddler-body h6 { 25 | margin-bottom: -0.5rem; 26 | } 27 | 28 | .tc-tiddler-body li + li { 29 | margin-top: 0.25em; 30 | } 31 | 32 | .tc-site-title, 33 | .tc-titlebar { 34 | font-size: 26px; 35 | line-height: 1.1; 36 | } 37 | 38 | .tc-title { 39 | letter-spacing: -0.5px; 40 | line-height: 1.1 41 | } 42 | 43 | .tc-tiddler-title-icon:empty, 44 | .tc-subtitle a.tc-tiddlylink-missing[href="#"] { 45 | display: none; 46 | } 47 | 48 | /* HTML TWEAKS */ 49 | 50 | pre { 51 | background-color: <>; 52 | border: 1px solid <>; 53 | } 54 | 55 | input, textarea { 56 | transition: border .14s ease-in-out; 57 | border: 1px solid <>; 58 | padding: .5em; 59 | border-radius: 5px; 60 | } 61 | 62 | select { 63 | border: 1px solid <>; 64 | padding: 1px 5px; 65 | border-radius: 5px; 66 | } 67 | 68 | :focus-visible { 69 | outline: 1px solid <>; 70 | outline-offset: 1px; 71 | } 72 | 73 | input:focus-visible, textarea:focus-visible, 74 | .tc-tiddler-frame input.tc-edit-texteditor:focus-visible, 75 | .tc-tiddler-frame textarea.tc-edit-texteditor:focus-visible, 76 | .tc-tiddler-frame iframe.tc-edit-texteditor:focus-visible { 77 | box-shadow: 0 0 3px 1px <>; 78 | border-color: <>; 79 | outline: none; 80 | } 81 | 82 | input[type="radio"] { 83 | vertical-align: sub; 84 | } 85 | 86 | input[type="radio"] { 87 | margin-right: 3px; 88 | } 89 | 90 | input, input[type="password"] { 91 | background: <>; 92 | border: 1px solid <>; 93 | } 94 | 95 | /* 96 | input[type="color"] { 97 | background: <>; 98 | border: 1px solid <>; 99 | padding: 5px 10px; 100 | height: 25px; 101 | } 102 | */ 103 | 104 | input[type="range"] { 105 | padding: 0; 106 | box-shadow: none; 107 | } 108 | 109 | textarea, input[type="text"], input[type="search"], input[type=""], input:not([type]) { 110 | background-color: <>; 111 | } 112 | 113 | hr { 114 | border: none; 115 | border-top: 1px solid <>; 116 | } 117 | 118 | html button { 119 | font-weight: 600; 120 | padding: 3px 9px; 121 | cursor: pointer; 122 | transition: box-shadow ease-in .1s; 123 | } 124 | 125 | details > summary { 126 | cursor: pointer; 127 | } 128 | 129 | .tc-sidebar-tab-open .tc-btn-invisible.tc-btn-mini svg { 130 | fill: <>; 131 | } 132 | 133 | .tc-sidebar-tab-open .tc-btn-invisible.tc-btn-mini:hover svg { 134 | fill: <>; 135 | } 136 | 137 | /* provides fallback when button-background color is blank */ 138 | html button { 139 | background: #f1f0ee; 140 | background: <>; 141 | color: #121212; 142 | color: <>; 143 | fill: #121212; 144 | fill: <>; 145 | border: 1px solid #cdc7c2; 146 | border-color: <>; 147 | border-radius: 5px; 148 | } 149 | 150 | button:disabled:not(.tc-btn-invisible), 151 | button:disabled:not(.tc-btn-invisible):hover { 152 | cursor: default; 153 | opacity: 53%; 154 | } 155 | 156 | button:not(:disabled):not(.tc-btn-invisible):hover { 157 | background-color: <>; 158 | } 159 | 160 | div:not(.tc-tab-buttons) button:not(.tc-btn-invisible):focus-visible { 161 | outline: none; 162 | box-shadow: 0 0 2px 1px <>;; 163 | } 164 | 165 | button.cv-secondary-btn { 166 | background: <>; 167 | color: <>; 168 | fill: <>; 169 | border: 1px solid <>;; 170 | } 171 | 172 | button.cv-secondary-btn:not(:disabled):hover { 173 | background-color: <>; 174 | } 175 | 176 | /* 177 | counter vanilla's ".tc-sidebar-lists button" overriding .tc-btn-invisible rule 178 | */ 179 | .tc-sidebar-lists .tc-btn-invisible { 180 | color: <>; 181 | fill: <>; 182 | } 183 | 184 | .tc-sidebar-lists button:disabled.tc-btn-invisible { 185 | color: <>; 186 | } 187 | 188 | .tc-btn-invisible.tc-missing-tiddler-label { 189 | color: <>; 190 | } 191 | 192 | /* POPUPS */ 193 | 194 | .tc-drop-down, 195 | .tc-block-dropdown { 196 | margin: 0px; 197 | padding: 5px 8px 5px 0px; 198 | /* max-height: 30vh; */ 199 | overflow-y: auto; 200 | font-weight: normal; 201 | border-radius: 2px; 202 | box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 1px 5px 0 rgba(0, 0, 0, 0.12); 203 | } 204 | 205 | .tc-block-dropdown .tc-tab-buttons a { 206 | display: revert; 207 | padding: 0px; 208 | } 209 | 210 | .tc-block-dropdown a.tc-tiddlylink-external { 211 | display: unset; 212 | } 213 | 214 | .tc-drop-down .tc-menu-list-item > a.tc-tiddlylink { 215 | white-space: normal; 216 | } 217 | 218 | .tc-drop-down a, .tc-drop-down button { 219 | text-align: left !important; 220 | } 221 | 222 | .tc-drop-down button.tc-btn-invisible { 223 | padding: 2px 3px; 224 | font-size: 85%; 225 | } 226 | 227 | .tc-drop-down a:hover, 228 | .tc-drop-down a.tc-tiddlylink:hover, 229 | .tc-drop-down button:hover, 230 | .tc-drop-down .tc-file-input-wrapper:hover button, 231 | .tc-drop-down button.tc-btn-invisible:hover svg, 232 | .tc-chosen, 233 | .tc-chooser-item:hover, 234 | a.tc-tiddlylink.tc-plugin-info:hover { 235 | color: <>; 236 | fill: <>; 237 | background-color: {{{ [colour[selection-background]alpha[0.45]] }}}; 238 | opacity: 1; 239 | text-decoration: none; 240 | } 241 | 242 | .tc-chosen { 243 | background-color: {{{ [colour[selection-background]alpha[0.65]] }}}; 244 | } 245 | 246 | .tc-drop-down .tc-btn-invisible { 247 | margin: 0 !important; 248 | text-align: left !important; 249 | font-weight: normal; 250 | } 251 | 252 | .tc-drop-down .tc-menu-list-item > a.tc-tiddlylink:hover { 253 | background: <>; 254 | color: <>; 255 | } 256 | 257 | .tc-block-dropdown a.tc-tiddlylink:hover { 258 | background-color: {{{ [colour[tiddler-link-foreground]alpha[0.1]] }}}; 259 | color: <>; 260 | } 261 | 262 | .tc-chosen, .tc-chooser-item:hover { 263 | } 264 | 265 | .tc-chooser-item a.tc-tiddlylink:hover { 266 | background-color: revert; 267 | } 268 | 269 | .tc-drafts-list a { 270 | font-size: 1.25em; 271 | font-weight: normal; 272 | border: 1px solid <>; 273 | background: <>; 274 | color: {{{ [colour[dirty-indicator]autocontrast[]] }}}; 275 | fill: {{{ [colour[dirty-indicator]autocontrast[]] }}}; 276 | } 277 | 278 | /* TABS */ 279 | 280 | div.tc-tab-set { 281 | box-shadow: none; 282 | } 283 | 284 | .tc-tab-set .tc-tab-content.tc-vertical { 285 | z-index: 100; 286 | border-left: 1px solid <>; 287 | } 288 | 289 | .tc-tab-set .tc-tab-buttons button { 290 | font-weight: 400; 291 | vertical-align: bottom; 292 | } 293 | 294 | .tc-tab-set .tc-tab-buttons button:not(.tc-tab-selected):hover { 295 | background: rgba(150,150,150,0.15); 296 | } 297 | 298 | .tc-tab-set .tc-tab-buttons button.tc-tab-selected:hover { 299 | background: <>; 300 | } 301 | 302 | .tc-tab-set .tc-tab-buttons:not(.tc-vertical) button.tc-tab-selected { 303 | font-weight: 600; 304 | } 305 | 306 | /* 307 | .tc-tab-set > .tc-tab-buttons:not(.tc-vertical) button { 308 | background: transparent; 309 | } 310 | */ 311 | 312 | .tc-tab-set > .tc-tab-buttons:not(.tc-vertical) button.tc-tab-selected { 313 | opacity: 1; 314 | } 315 | 316 | .tc-tab-set > .tc-tab-buttons.tc-vertical > button { 317 | text-align: left; 318 | } 319 | 320 | .tc-tab-set > .tc-tab-buttons.tc-vertical > button.tc-tab-selected { 321 | background-color: <>; 322 | color: <>; 323 | font-weight: 600; 324 | } 325 | 326 | /* TOPBAR */ 327 | 328 | .cv-topbar-wrapper .cv-topbar-title, 329 | .cv-sidebar .cv-topbar-title { 330 | font-size: 20px; 331 | font-weight: 600; 332 | line-height: 1; 333 | } 334 | 335 | .cv-topbar-main > .tc-page-controls { 336 | font-size: 1em; 337 | } 338 | 339 | .cv-topbar-wrapper .tc-btn-invisible, 340 | button.cv-topbar-btn { 341 | font-size: 16px; 342 | line-height: 1; 343 | } 344 | 345 | /* BOTTOMBAR */ 346 | 347 | .cv-bottombar-wrapper { 348 | background: <>; 349 | } 350 | 351 | .cv-bottombar-wrapper .tc-page-controls svg { 352 | fill: <>; 353 | } 354 | 355 | .cv-bottombar-wrapper .tc-page-controls button.tc-selected svg { 356 | fill: #303030; 357 | } 358 | 359 | .cv-bottombar-wrapper .tc-page-controls svg .tc-image-cloud-idle { 360 | fill: <>; 361 | } 362 | 363 | /* SEARCHBAR */ 364 | 365 | .cv-search-bar input { 366 | border-radius: 3px; 367 | line-height: 1.45; 368 | } 369 | 370 | .tc-search-drop-down a { 371 | white-space: nowrap; 372 | text-overflow: ellipsis; 373 | font-size: .92em; 374 | } 375 | 376 | /* 377 | .tc-search-drop-down a:hover { 378 | white-space: normal; 379 | } 380 | */ 381 | 382 | /* SIDEBAR */ 383 | 384 | div.cv-sidebar { 385 | font-size: .95em; 386 | background-color: <>; 387 | color: <>; 388 | fill: <>; 389 | } 390 | 391 | .cv-sidebar .tc-tab-set.tc-sidebar-tabs-main > .tc-tab-buttons > button { 392 | text-transform: uppercase; 393 | } 394 | 395 | .cv-sidebar .tc-tab-set.tc-sidebar-tabs-main > .tc-tab-buttons > .tc-tab-selected, 396 | .cv-sidebar .tc-tab-set.tc-sidebar-tabs-main .tc-tab-buttons.tc-vertical > .tc-tab-selected { 397 | color: <>; 398 | font-weight: 600; 399 | } 400 | 401 | .tc-tab-buttons.tc-sidebar-tabs-main > button { 402 | flex-grow: 1; 403 | } 404 | 405 | .tc-sidebar-tabs button.tc-tiddlylink, 406 | .tc-sidebar-tabs a.tc-tiddlylink { 407 | color: <>; 408 | } 409 | 410 | .tc-sidebar-tabs-main a.tc-tiddlylink { 411 | color: <>; 412 | } 413 | 414 | .tc-sidebar-tabs-main a.tc-tiddlylink:hover { 415 | color: <>; 416 | background-color: <>; 417 | } 418 | 419 | .cv-sidebar .tc-tab-content.tc-sidebar-tabs-more > div > .tc-menu-list-item, 420 | .cv-sidebar .tc-tab-content.tc-sidebar-tabs-more .tc-menu-list-item > .tc-menu-list-subitem { 421 | white-space: nowrap; 422 | text-overflow: ellipsis; 423 | line-height: 1.2; 424 | } 425 | 426 | .tc-sidebar-tabs-main .tc-menu-list-subitem { 427 | overflow-x: hidden; 428 | text-overflow: ellipsis; 429 | } 430 | 431 | .cv-sidebar .tc-tab-content.tc-sidebar-tabs-more > div > .tc-menu-list-item:hover, 432 | .cv-sidebar .tc-tab-content.tc-sidebar-tabs-more .tc-menu-list-item > .tc-menu-list-subitem:hover { 433 | white-space: normal; 434 | background-color: <>; 435 | } 436 | 437 | .cv-sidebar .tc-sidebar-tabs-more .tc-tab-set .tc-menu-list-item { 438 | white-space: normal; 439 | line-height: 1.3; 440 | } 441 | 442 | .cv-sidebar .tc-tab-content div[class^="tc-btn-"] button, 443 | .tc-sidebar-lists .tc-tab-content div[class^="tc-btn-"] button { 444 | background-color: <>; 445 | color: <>; 446 | fill: <>; 447 | } 448 | 449 | .cv-sidebar .tc-tab-content div[class^="tc-btn-"] button:hover { 450 | background-color: <>; 451 | } 452 | 453 | /* ACCENT TOPBAR: YES */ 454 | 455 | <$reveal type="nomatch" state="$:/themes/cdr/captivate/settings/accent-topbar" text="no" default="yes"> 456 | .cv-topbar-wrapper { 457 | background: <>; 458 | /* 459 | box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.3); 460 | */ 461 | } 462 | 463 | .cv-topbar-wrapper .cv-topbar-title, 464 | .cv-topbar-wrapper .cv-topbar-btn, 465 | .cv-topbar-wrapper .cv-search-bar > .tc-btn-invisible, 466 | .cv-topbar-wrapper .tc-page-controls > .tc-btn-invisible svg { 467 | color: {{{ [colour[primary]autocontrast[]] }}}; 468 | fill: {{{ [colour[primary]autocontrast[]] }}}; 469 | } 470 | 471 | .cv-search-bar input:not(:focus-visible) { 472 | background-color: {{{ [[#fff]alpha[0.2]over] }}}; 473 | color: {{{ [[#fff]alpha[0.2]overautocontrast[]] }}}; 474 | } 475 | 476 | .cv-search-bar input:not(:focus-visible)::placeholder { 477 | color: {{{ [colour[primary]deviate[]autocontrast[]] }}}; 478 | opacity: 0.85; 479 | } 480 | 481 | @media (min-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 482 | div.cv-sidebar { 483 | border-right: 1px solid <>; 484 | } 485 | } 486 | 487 | .tc-tiddler-frame { 488 | box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.20); 489 | } 490 | 491 | 492 | /* ACCENT TOPBAR: NO */ 493 | 494 | <$reveal type="match" state="$:/themes/cdr/captivate/settings/accent-topbar" text="no"> 495 | .cv-topbar-wrapper, 496 | .cv-topbar-wrapper button:hover { 497 | background: <>; 498 | } 499 | 500 | .cv-topbar-wrapper .cv-topbar-title, 501 | .cv-topbar-wrapper .cv-topbar-btn, 502 | .cv-topbar-wrapper .cv-search-bar > .tc-btn-invisible, 503 | .cv-topbar-wrapper .tc-page-controls > button svg { 504 | color: <>; 505 | fill: <>; 506 | } 507 | 508 | .cv-topbar-wrapper button:hover .tc-image-cloud-idle, 509 | .cv-topbar-wrapper button .tc-image-cloud-idle { 510 | fill: <>; 511 | } 512 | 513 | <$vars bgcolor={{{ [colour[page-background]deviate[]] }}} fgcolor={{{ [colour[page-background]deviate[]autocontrast[]] }}} > 514 | .cv-search-bar input:not(:focus-visible) { 515 | background-color: <>; 516 | color: <>; 517 | } 518 | .cv-search-bar input:not(:focus-visible)::placeholder { 519 | color: <>; 520 | opacity: 0.7; 521 | } 522 | 523 | 524 | .tc-tiddler-frame { 525 | box-shadow: 2px 1px 6px 2px rgba(0,0,0,0.10); 526 | } 527 | 528 | 529 | /* VANILLA TWEAKS */ 530 | 531 | button.tc-untagged-label.tc-tag-label { 532 | color: <$macrocall $name="color-autocontrast" color={{{ [colour[untagged-background]] }}} />; 533 | } 534 | 535 | .tc-tiddler-body button { 536 | font-size: 0.9em; 537 | } 538 | 539 | <$reveal type="match" state="$:/themes/tiddlywiki/vanilla/options/codewrapping" text="pre"> 540 | .tc-tiddler-body > pre { 541 | overflow-x: scroll; 542 | overflow-wrap: normal; 543 | } 544 | 545 | 546 | 547 | .tc-modal { 548 | border-radius: 6px; 549 | box-shadow: 0 3px 7px rgba(0,0,0,0.3); 550 | } 551 | 552 | .tc-modal-footer { 553 | border-radius: 0 0 6px 6px; 554 | } 555 | 556 | /* SCROLLBARS */ 557 | 558 | div::-webkit-scrollbar { 559 | height: 8px; 560 | width: 8px; 561 | background: rgba(256, 256, 256, 0.2); 562 | } 563 | 564 | div::-webkit-scrollbar-thumb { 565 | background: <>; 566 | border-radius: 3px; 567 | } 568 | 569 | /* LINKS */ 570 | 571 | /* internal */ 572 | a.tc-tiddlylink, 573 | a.tc-tiddlylink:visited { 574 | text-decoration:none; 575 | } 576 | 577 | .tc-sidebar-lists a.tc-tiddlylink:hover { 578 | text-decoration:none; 579 | } 580 | 581 | /* external */ 582 | a.tc-tiddlylink-external, 583 | a.tc-tiddlylink-external:visited { 584 | text-decoration: none; 585 | } 586 | 587 | a.tc-tiddlylink:hover, 588 | a.tc-tiddlylink-external:hover { 589 | text-decoration-line: underline; 590 | text-underline-offset: 2px; 591 | } 592 | 593 | @media screen { 594 | a.tc-tiddlylink-external::after { 595 | content: ""; 596 | height: 10px; 597 | width: 10px; 598 | display: inline-block; 599 | -webkit-mask: url("data:image/svg+xml,%3Csvg version='1.1' viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m7.5 0.5h4v4m-8-4h-3v11h11v-3m0-8-6.5 6.5' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.25'/%3E%3C/svg%3E"); 600 | mask: url("data:image/svg+xml,%3Csvg version='1.1' viewBox='0 0 12 12' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m7.5 0.5h4v4m-8-4h-3v11h11v-3m0-8-6.5 6.5' fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.25'/%3E%3C/svg%3E"); 601 | -webkit-mask-size: cover; 602 | mask-size: cover; 603 | background-color: currentcolor; 604 | margin: 0 2px 0 3px; 605 | -webkit-print-color-adjust: exact; 606 | color-adjust: exact; 607 | print-color-adjust: exact; 608 | } 609 | } 610 | 611 | a.tc-tiddlylink.tc-plugin-info:hover > .tc-plugin-info-chunk > svg { 612 | fill: <>; 613 | } 614 | 615 | .tc-tree li span { 616 | color: <>; 617 | } 618 | 619 | .tc-tiddler-body code { 620 | font-size: 0.95em; 621 | } 622 | 623 | .tc-tiddler-info { 624 | 625 | } 626 | 627 | /* FAB BUTTONS */ 628 | .tc-page-controls button.cv-fab-item { 629 | font-size: 16px; 630 | border-radius: 50%; 631 | border: none; 632 | 633 | background-color: <>; 634 | box-shadow: 0 2px 2px 0 rgba(0,0,0,0.14), 0 3px 1px -2px rgba(0,0,0,0.12), 0 1px 5px 0 rgba(0,0,0,0.20); 635 | <> 636 | } 637 | 638 | button.cv-fab-item svg { 639 | fill: <>; 640 | } 641 | 642 | .cv-topbar-wrapper .tc-image-cloud-idle { 643 | fill: <>; 644 | } 645 | 646 | button.cv-fab-item .tc-image-cloud-idle { 647 | fill: {{{ [colour[fab-background]] }}}; 648 | } 649 | 650 | .tc-page-controls button.cv-fab-item:hover { 651 | background: <>; 652 | } 653 | 654 | .tc-page-controls button.cv-fab-item:hover svg { 655 | fill: {{{ [colour[fab-background-hover]autocontrast[]] }}}; 656 | color: {{{ [colour[fab-background-hover]autocontrast[]] }}}; 657 | } 658 | 659 | button.cv-fab-item:hover .tc-image-cloud-idle { 660 | fill: <>; 661 | } 662 | 663 | /* PORTRAIT */ 664 | 665 | @media (max-width: {{$:/themes/tiddlywiki/vanilla/metrics/sidebarbreakpoint}}) { 666 | .cv-sidebar .tc-sidebar-tabs { 667 | box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.5); 668 | } 669 | 670 | .tc-block-dropdown.cv-search-dropdown { 671 | -webkit-transform: unset; 672 | -moz-transform: unset; 673 | -ms-transform: unset; 674 | -o-transform: unset; 675 | transform: unset; 676 | } 677 | 678 | <$reveal type="nomatch" state="$:/view" text="zoomin"> 679 | .tc-drop-down, 680 | .tc-block-dropdown { 681 | -webkit-transform: translateY(-50%); 682 | -moz-transform: translateY(-50%); 683 | -ms-transform: translateY(-50%); 684 | -o-transform: translateY(-50%); 685 | transform: translateY(-50%); 686 | text-align: left; 687 | } 688 | 689 | 690 | .tc-block-dropdown.cv-search-dropdown { 691 | box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.2), 0 4px 5px 0 rgba(0, 0, 0, 0.14), 0 1px 10px 0 rgba(0, 0, 0, 0.12); 692 | } 693 | 694 | .tc-tiddler-frame { 695 | box-shadow: 0px 2px 3px rgba(0, 0, 0, 0.5); 696 | } 697 | } 698 | 699 | @supports (-webkit-touch-callout: none) { 700 | /* CSS specific to iOS devices */ 701 | input, textarea { 702 | font-size: 16px; /* prevents automatic zoom-in with small fonts */ 703 | } 704 | } 705 | 706 | <$reveal type="match" state="$:/layout" text="$:/themes/cdr/captivate/ui/PageLayout"> 707 | {{$:/themes/cdr/captivate/css/base-layout}} 708 | 709 | 710 | <$reveal type="match" stateTitle={{$:/palette}} stateField="color-scheme" text="dark"> 711 | .tc-tiddler-body p { 712 | word-spacing: 0.1em; 713 | } 714 | 715 | mark { 716 | background-color: #eeee00; 717 | } 718 | 719 | 720 | @media print { 721 | :root { 722 | color-scheme: light; 723 | } 724 | .tc-tiddler-body a[href^=http]:after { 725 | content:" <" attr(href) "> "; 726 | font-size: 0.85em; 727 | } 728 | 729 | .tc-plugin-info-dropdown-body { 730 | background-color: unset; 731 | } 732 | 733 | html button, .tc-tag-label { 734 | border: 1px buttontext solid; 735 | background-color: unset; 736 | color: buttontext; 737 | fill: buttontext; 738 | } 739 | 740 | .tc-tab-buttons button.tc-tab-selected { 741 | background-color: transparent; 742 | color: buttontext; 743 | fill: buttontext; 744 | } 745 | } 746 | 747 | -------------------------------------------------------------------------------- /plugins/cdr/colorlab/lib/convert.js: -------------------------------------------------------------------------------- 1 | /*\ 2 | title: $:/plugins/cdr/colorlab/lib/convert.js 3 | type: application/javascript 4 | module-type: library 5 | 6 | Color manipulation library 7 | 8 | Color componnent 'none' will be interpreted as NaN and in most cases, behaves as a zero value. 9 | See https://www.w3.org/TR/css-color-4/#missing for more details. 10 | \*/ 11 | (function() { 12 | /*jslint node: true, browser: true */ 13 | /*global $tw: false */ 14 | "use strict"; 15 | 16 | // given white point in (x,y), returns its XYZ coordinate 17 | function whitepoint(x,y) {return [x/y, 1, (1-x-y)/y];} 18 | 19 | function uv(p) { 20 | return [4*p[0] / (p[0] + 15*p[1] + 3*p[2]), 9*p[1] / (p[0] + 15*p[1] + 3*p[2])]; 21 | } 22 | 23 | // given an 3x3 matrix M and a vector v, multiple M x v 24 | function matmul(M,v) { 25 | return v.map(function (e /*not used*/,i,a) { 26 | return M[i][0]*a[0] + M[i][1]*a[1] + M[i][2]*a[2]; 27 | }); 28 | } 29 | 30 | var CIE = { 31 | ε: 216/24389, 32 | κ: 24389/27, 33 | ε_cbrt: 6/29, 34 | illuminant: function(x,y) { 35 | var wp = whitepoint(x,y); 36 | return { 37 | white: Object.freeze(wp), 38 | uvref: Object.freeze(uv(wp)) 39 | }; 40 | } 41 | }; 42 | 43 | CIE.D65 = CIE.illuminant(0.3127,0.3290); 44 | CIE.D50 = CIE.illuminant(0.3457,0.3585); 45 | 46 | var Convert = {}; 47 | 48 | function clamp(v,min,max) { 49 | return Math.min(Math.max(v,min),max); 50 | } 51 | 52 | function clamp360(v) { 53 | return ((v % 360) + 360) % 360; 54 | } 55 | 56 | Convert.clamp = clamp; 57 | Convert.clamp360 = clamp360; 58 | 59 | Convert.spaces = {}; 60 | 61 | Convert.spaces.xyz = { 62 | id: "xyz", 63 | name: "XYZ", 64 | coords: [{name:"X",range:[-Infinity,Infinity]}, 65 | {name:"Y",range:[-Infinity,Infinity]}, 66 | {name:"Z",range:[-Infinity,Infinity]}], 67 | white: CIE.D65.white, 68 | 69 | fromXYZ: function(xyz) {return xyz;}, 70 | toXYZ: function(xyz) {return xyz;}, 71 | 72 | toString: function(coords,alpha) { 73 | coords = coords.map(function(c) {return numstr(c);}); 74 | return "xyz(" + coords.join(" ") + appendAlpha(alpha) + ")"; 75 | } 76 | }; 77 | 78 | Convert.spaces.rgb = { 79 | id: "rgb", 80 | name: "sRGB", 81 | coords: [{name:"r",range:[0,1]}, 82 | {name:"g",range:[0,1]}, 83 | {name:"b",range:[0,1]}], 84 | white: CIE.D65.white, 85 | intoGamut: true, 86 | 87 | // extended transfer function: if x < 0, returns -f(-x) 88 | toLinear: function(rgb) { 89 | function invCompand(c) { 90 | var sign = c < 0 ? -1 : 1; 91 | c = Math.abs(c); 92 | return sign * (c <= 0.04045 ? c/12.92 : Math.pow((c+0.055)/1.055,2.4)); 93 | } 94 | 95 | // expand gamma correction 96 | return rgb.map(invCompand); 97 | }, 98 | 99 | // extended transfer function: if x < 0, returns -f(-x) 100 | toGamma: function(lrgb) { 101 | function compand(c) { 102 | var sign = c < 0 ? -1 : 1; 103 | c = Math.abs(c); 104 | return sign * (c <= 0.0031308 ? 12.92*c : 1.055*Math.pow(c,5/12)-0.055); 105 | } 106 | // compress linear rgb with gamma correction 107 | return lrgb.map(compand) 108 | }, 109 | 110 | // sRGB to xyz 111 | toXYZ: (function() { 112 | // computed from white point 113 | var M = [[0.4123907992659595, 0.357584339383878 , 0.1804807884018343], 114 | [0.2126390058715103, 0.7151686787677559, 0.0721923153607337], 115 | [0.0193308187155918, 0.1191947797946259, 0.9505321522496605]]; 116 | return function(rgb) { 117 | return matmul(M,this.toLinear(rgb)); 118 | } 119 | })(), 120 | 121 | // xyz to sRGB 122 | fromXYZ: (function() { 123 | var M = [[ 3.240969941904522 , -1.5373831775700937, -0.4986107602930033], 124 | [-0.9692436362808798, 1.8759675015077206, 0.0415550574071756], 125 | [ 0.0556300796969936, -0.2039769588889765, 1.0569715142428786]]; 126 | return function(xyz) { 127 | return this.toGamma(matmul(M,xyz)); 128 | } 129 | })(), 130 | 131 | toString: function(coords,alpha) { 132 | var rgb = coords.map(function(x) {return Math.round(x*255);}); 133 | 134 | function hex(n) { 135 | return isNaN(n) ? '00' : ('0' + n.toString(16)).slice(-2); 136 | } 137 | 138 | if (alpha < 1) { 139 | return "rgba(" + rgb.join(",") + "," + numstr(alpha) + ")"; 140 | } else { 141 | return "#" + hex(rgb[0]) + hex(rgb[1]) + hex(rgb[2]); 142 | } 143 | } 144 | }; 145 | 146 | Convert.spaces.hsl = { 147 | id: "hsl", 148 | name: "HSL", 149 | coords: [{name:"h",range:[0,360],isAngle:true}, 150 | {name:"s",range:[0,1]}, 151 | {name:"l",range:[0,1]}], 152 | white: CIE.D65.white, 153 | intoGamut: true, 154 | 155 | toString: function(hsl,alpha) { 156 | return "hsl(" 157 | + (isNaN(hsl[0]) ? 0 : Math.round(hsl[0])) + " " 158 | + numstr(Math.round(hsl[1]*100)) + "% " 159 | + numstr(Math.round(hsl[2]*100)) + "% " + appendAlpha(alpha) + ")"; 160 | }, 161 | 162 | from: { 163 | "rgb": function(rgb) { 164 | var r = rgb[0], g = rgb[1], b = rgb[2]; 165 | var max = Math.max(r, g, b); 166 | var min = Math.min(r, g, b); 167 | var d = max - min; 168 | var h = NaN, 169 | s = 0, // zero when light is 0 or 1 170 | l = (min+max)/2; 171 | 172 | if(d !== 0) { 173 | s = d / (l < 0.5 ? (max + min) : (2 - max - min)); 174 | 175 | switch (max) { 176 | case r: h = (g - b) / d + (g < b ? 6 : 0); break; 177 | case g: h = (b - r) / d + 2; break; 178 | case b: h = (r - g) / d + 4; 179 | } 180 | 181 | h = h * 60; 182 | } 183 | 184 | return [h, s, l]; // deg, [0..1], [0..1] 185 | } 186 | }, 187 | 188 | to: { 189 | // Adapted from https://www.w3.org/TR/css-color-4/#hsl-to-rgb 190 | "rgb": function(hsl) { 191 | hsl = hsl.map(function (n) { return isNaN(n) ? 0 : n; }); 192 | 193 | var h = hsl[0], s = hsl[1], l = hsl[2]; 194 | 195 | h = (((h % 360) + 360) % 360); 196 | 197 | var f = function(n) { 198 | var k = (n + h/30) % 12; 199 | var a = s * Math.min(l, 1 - l); 200 | return l - a * Math.max(-1, Math.min(k - 3, 9 - k, 1)); 201 | } 202 | return [f(0),f(8),f(4)]; // normalized to [0..1] 203 | } 204 | } 205 | }; 206 | 207 | Convert.spaces.p3 = { 208 | id: "p3", 209 | name: "display-p3", 210 | coords: [{name:"r",range:[0,1]}, 211 | {name:"g",range:[0,1]}, 212 | {name:"b",range:[0,1]} ], 213 | white: CIE.D65.white, 214 | intoGamut: true, 215 | 216 | toLinear: Convert.spaces.rgb.toLinear, 217 | 218 | toGamma: Convert.spaces.rgb.toGamma, 219 | 220 | toXYZ: (function() { 221 | // computed from white point 222 | var M = [[0.486570948648216, 0.2656676931690931, 0.1982172852343625], 223 | [0.2289745640697487, 0.6917385218365063, 0.079286914093745 ], 224 | [0, 0.0451133818589026, 1.0439443689009757]]; 225 | return function(rgb) { 226 | return matmul(M,this.toLinear(rgb)); 227 | } 228 | })(), 229 | 230 | fromXYZ: (function() { 231 | var M = [[ 2.4934969119414263, -0.9313836179191244, -0.4027107844507171], 232 | [-0.8294889695615749, 1.7626640603183465, 0.0236246858419436], 233 | [ 0.0358458302437845, -0.0761723892680418, 0.9568845240076874]]; 234 | return function(xyz) { 235 | return this.toGamma(matmul(M,xyz)); 236 | } 237 | })(), 238 | 239 | toString: function(coords,alpha) { 240 | coords = coords.map(function(c) {return numstr(c);}); 241 | return "color(display-p3 " + coords.join(" ") + appendAlpha(alpha) + ")"; 242 | } 243 | }; 244 | 245 | Convert.spaces.lab = { 246 | id: "lab", 247 | name: "Lab", 248 | coords: [{name:"l",range:[0,100]}, 249 | {name:"a",range:[-Infinity,Infinity]}, 250 | {name:"b",range:[-Infinity,Infinity]} ], 251 | white: CIE.D50.white, 252 | 253 | toXYZ: function(lab) { 254 | var f=[]; 255 | 256 | f[1] = (lab[0] + 16)/116; 257 | f[0] = lab[1]/500 + f[1]; 258 | f[2] = f[1] - lab[2]/200; 259 | 260 | var xyz = f.map(function(value,i) { 261 | var cubed = value * value * value; 262 | return (cubed > CIE.ε ? cubed : (value * 116 - 16) / CIE.κ) * this.white[i]; 263 | },this); 264 | 265 | if (this.white != Convert.spaces.xyz.white) { 266 | xyz = Convert.chromaticAdaptation(this.white,Convert.spaces.xyz.white,xyz); 267 | } 268 | return xyz; 269 | }, 270 | 271 | fromXYZ: function(xyz) { 272 | if (this.white != Convert.spaces.xyz.white) { 273 | xyz = Convert.chromaticAdaptation(Convert.spaces.xyz.white,this.white,xyz); 274 | } 275 | 276 | xyz = xyz.map(function(value,i) { 277 | return value / this.white[i]; 278 | },this); 279 | 280 | var f = xyz.map(function(value,i) { 281 | return value > CIE.ε ? Math.cbrt(value) : (CIE.κ * value + 16)/116; 282 | }); 283 | 284 | return [ 285 | clamp((116 * f[1]) - 16,0,100), // L 286 | 500 * (f[0] - f[1]), // a 287 | 200 * (f[1] - f[2]) // b 288 | ]; 289 | }, 290 | 291 | toString: function(lab,alpha) { 292 | return "lab(" 293 | + numstr(lab[0]) + "% " 294 | + numstr(lab[1]) + " " 295 | + numstr(lab[2]) + appendAlpha(alpha) + ")"; 296 | } 297 | }; 298 | 299 | /* https://www.magnetkern.de/srlab2.pdf */ 300 | Convert.spaces.srlab2 = { 301 | id: "srlab2", 302 | name: "SRLAB2", 303 | coords: [{name: "l", range:[0,100]}, 304 | {name: "a", range:[-Infinity, Infinity]}, 305 | {name: "b", range:[-Infinity, Infinity]}], 306 | white: CIE.D65.white, 307 | 308 | fromXYZ: (function() { 309 | // M_HPE * inv(M_CAT02) * diagonal(1/rgb_ref) * M_CAT02 310 | var M1 = [ 311 | [ 0.4239866073983792, 0.6933061285086612, -0.0884036796338899], 312 | [-0.203631183252087 , 1.1536283980317619, 0.0366500922424727], 313 | [-0.0007593175873917, -0.0010007075130392, 0.919806506785842 ]]; 314 | var inv_M_HPE = [ 315 | [ 1.910196834052035 , -1.1121238927878747, 0.2019079567674994], 316 | [ 0.3709500882486886, 0.6290542573926132, -0.0000080551421844], 317 | [ 0. , 0. , 1. ]]; 318 | var f = function(w) { 319 | return w <= CIE.ε ? w * 0.01 * CIE.κ : 1.16 * Math.cbrt(w) - 0.16; 320 | } 321 | 322 | return function(xyz) { 323 | xyz = matmul(M1,xyz).map(f); 324 | xyz = matmul(inv_M_HPE,xyz); 325 | var L = 100 * xyz[1], 326 | a = 500/1.16 * (xyz[0] - xyz[1]), 327 | b = 200/1.16 * (xyz[1] - xyz[2]); 328 | 329 | return [L,a,b]; 330 | } 331 | })(), 332 | 333 | toXYZ: (function() { 334 | // M_HPE * inv(M_CAT02) * diagonal(1/rgb_ref) * M_CAT02 335 | var M_HPE = [ 336 | [ 0.38971, 0.68898, -0.07868], 337 | [-0.22981, 1.18340, 0.04641], 338 | [ 0.00000, 0.00000, 1.0000]]; 339 | var inv_M1 = [ 340 | [ 1.8306560666900926, -1.099994712882931 , 0.2197762666838433], 341 | [ 0.3230766443179263, 0.6726717504705783, 0.0042483744450524], 342 | [ 0.001862733695097 , -0.0001762301699639, 1.0873712286074086]]; 343 | var f = function(w) { 344 | return w <= 0.08 ? w * 100 / CIE.κ : Math.pow((w + 0.16)/1.16,3); 345 | } 346 | 347 | return function(lab) { 348 | var y = 0.01 * lab[0], 349 | x = lab[1] * 1.16/500 + y, 350 | z = y - lab[2] * 1.16/200; 351 | 352 | var xyz = matmul(M_HPE,[x,y,z]); 353 | xyz = matmul(inv_M1,xyz.map(f)); 354 | 355 | return xyz; 356 | } 357 | })(), 358 | 359 | from: { 360 | "rgb": function(rgb) { 361 | var linRGB = Convert.spaces.rgb.toLinear(rgb), 362 | x = 0.3205631863289935 * linRGB[0] + 0.6369045416942921 * linRGB[1] + 0.0425422719767143 * linRGB[2], 363 | y = 0.1620392455748646 * linRGB[0] + 0.7565920747424774 * linRGB[1] + 0.0813686796826581 * linRGB[2], 364 | z = 0.0172546877985969 * linRGB[0] + 0.1086489392821993 * linRGB[1] + 0.8740963729192033 * linRGB[2]; 365 | 366 | x = x <= 216/24389 ? x * 24389 / 2700 : 1.16 * Math.cbrt(x) - 0.16; 367 | y = y <= 216/24389 ? y * 24389 / 2700 : 1.16 * Math.cbrt(y) - 0.16; 368 | z = z <= 216/24389 ? z * 24389 / 2700 : 1.16 * Math.cbrt(z) - 0.16; 369 | 370 | var lightness = 37.0950 * x + 62.9054 * y - 0.0008 * z; 371 | var a = 663.4684 * x - 750.5078 * y + 87.0328 * z; 372 | var b = 63.9569 * x + 108.4576 * y - 172.4152 * z; 373 | 374 | return [lightness,a,b]; 375 | } 376 | }, 377 | 378 | to: { 379 | "rgb": function(lab) { 380 | var x = 0.01 * lab[0] + 0.000904127 * lab[1] + 0.000456344 * lab[2]; 381 | var y = 0.01 * lab[0] - 0.000533159 * lab[1] - 0.000269178 * lab[2]; 382 | var z = 0.01 * lab[0] - 0.005800000 * lab[2]; 383 | if (x <= 0.08) x *= 2700 / 24389; 384 | else x = Math.pow((x + 0.16) / 1.16,3); 385 | if (y <= 0.08) y *= 2700 / 24389; 386 | else y = Math.pow((y + 0.16) / 1.16,3); 387 | if (z <= 0.08) z *= 2700 / 24389; 388 | else z = Math.pow((z + 0.16) / 1.16,3); 389 | 390 | var rd = 5.435479909003638 * x - 4.599116163648537 * y + 0.1635818998458092 * z; 391 | var gn = -1.1681930516161254 * x + 2.32806589521468 * y - 0.1598611616680385 * z; 392 | var bl = 0.0379082079460666 * x - 0.1985886018050641 * y + 1.1606800147769185 * z; 393 | 394 | return Convert.spaces.rgb.toGamma([rd,gn,bl]); 395 | } 396 | }, 397 | 398 | toString: function(lab,alpha) { 399 | return "srlab2(" 400 | + numstr(lab[0]) + "% " 401 | + numstr(lab[1]) + " " 402 | + numstr(lab[2]) + appendAlpha(alpha) + ")"; 403 | } 404 | }; 405 | 406 | /* https://bottosson.github.io/posts/oklab/ */ 407 | Convert.spaces.oklab = { 408 | id: "oklab", 409 | name: "Oklab", 410 | coords: [{name:"l",range:[0,100]}, 411 | {name:"a",range:[-Infinity,Infinity]}, 412 | {name:"b",range:[-Infinity,Infinity]} ], 413 | white: CIE.D65.white, 414 | 415 | _lms2lab: (function() { 416 | var M2 = [[ 0.2104542553, 0.7936177850, -0.0040720468], 417 | [ 1.9779984951, -2.4285922050, 0.4505937099], 418 | [ 0.0259040371, 0.7827717662, -0.8086757660]]; 419 | return function(lms) { 420 | lms[0] = Math.cbrt(lms[0]); 421 | lms[1] = Math.cbrt(lms[1]); 422 | lms[2] = Math.cbrt(lms[2]); 423 | 424 | var lab = matmul(M2,lms); 425 | lab[0] = clamp(lab[0] * 100,0,100); 426 | return lab; 427 | }; 428 | })(), 429 | 430 | _lab2lms: (function() { 431 | var M2inv = [[ 1, 0.3963377921737677, 0.2158037580607588], 432 | [ 1, -0.1055613423236563, -0.0638541747717059], 433 | [ 1, -0.0894841820949657, -1.2914855378640917]]; 434 | return function(lab) { 435 | lab = lab.slice(0); 436 | lab[0] /= 100; 437 | var lms = matmul(M2inv,lab); 438 | 439 | lms[0] = Math.pow(lms[0],3); 440 | lms[1] = Math.pow(lms[1],3); 441 | lms[2] = Math.pow(lms[2],3); 442 | return lms; 443 | }; 444 | })(), 445 | 446 | toXYZ: (function() { 447 | var M1inv = [[ 1.2270138511035211, -0.5577999806518222, 0.2812561489664678], 448 | [-0.0405801784232806, 1.11225686961683 , -0.0716766786656012], 449 | [-0.0763812845057069, -0.4214819784180127, 1.5861632204407947]]; 450 | return function(lab) { 451 | var lms = this._lab2lms(lab); 452 | 453 | return matmul(M1inv,lms); 454 | } 455 | })(), 456 | 457 | fromXYZ: (function() { 458 | var M1 = [[ 0.8189330101, 0.3618667424, -0.1288597137], 459 | [ 0.0329845436, 0.9293118715, 0.0361456387], 460 | [ 0.0482003018, 0.2643662691, 0.6338517070]]; 461 | return function(xyz) { 462 | var lms = matmul(M1,xyz); 463 | 464 | return this._lms2lab(lms); 465 | } 466 | })(), 467 | 468 | from: { 469 | "rgb": (function() { 470 | var M = [[ 0.4122214708, 0.5363325363, 0.0514459929], 471 | [ 0.2119034982, 0.6806995451, 0.1073969566], 472 | [ 0.0883024619, 0.2817188376, 0.6299787005]]; 473 | return function(rgb) { 474 | var linRGB = Convert.spaces.rgb.toLinear(rgb), 475 | lms = matmul(M,linRGB); 476 | return this._lms2lab(lms); 477 | } 478 | })() 479 | }, 480 | 481 | to: { 482 | "rgb": (function() { 483 | var Minv = [[ 4.0767416621, -3.3077115913, 0.2309699292], 484 | [-1.2684380046, 2.6097574011, -0.3413193965], 485 | [-0.0041960863, -0.7034186147, 1.7076147010]]; 486 | return function(lab) { 487 | var lms = this._lab2lms(lab), 488 | linRGB = matmul(Minv,lms); 489 | return Convert.spaces.rgb.toGamma(linRGB); 490 | }; 491 | })() 492 | }, 493 | 494 | toString: function(lab,alpha) { 495 | return "oklab(" 496 | + numstr(lab[0]) + "% " 497 | + numstr(lab[1]) + " " 498 | + numstr(lab[2]) + appendAlpha(alpha) + ")"; 499 | } 500 | }; 501 | 502 | Convert.spaces.luv = { 503 | id: "luv", 504 | name: "Luv", 505 | coords: [{name:"l",range:[0,100]}, 506 | {name:"u",range:[-Infinity,Infinity]}, 507 | {name:"v",range:[-Infinity,Infinity]} ], 508 | white: CIE.D65.white, 509 | uvref: CIE.D65.uvref, 510 | 511 | toXYZ: function(luv) { 512 | if (luv[0] === 0) { 513 | return [0,0,0]; 514 | } 515 | 516 | var L = luv[0],u = luv[1],v = luv[2]; 517 | var u0 = this.uvref[0]; 518 | var v0 = this.uvref[1]; 519 | 520 | var u1 = u / (13 * L) + u0; 521 | var v1 = v / (13 * L) + v0; 522 | var d = 4 * v1; 523 | 524 | var y = (L > CIE.κ * CIE.ε) ? Math.pow((L + 16) / 116,3) : L / CIE.κ; 525 | var x = 9 * y * u1 / d; 526 | var z = y * (12 - 3 * u1 - 20 * v1) / d; 527 | 528 | return [x,y,z]; 529 | }, 530 | 531 | fromXYZ: function(xyz) { 532 | var uR = this.uvref[0]; 533 | var vR = this.uvref[1]; 534 | 535 | var denom = xyz[0] + 15*xyz[1] + 3*xyz[2]; 536 | if (denom === 0) { 537 | return [0,0,0]; 538 | } 539 | var u1 = 4 * xyz[0] / denom; 540 | var v1 = 9 * xyz[1] / denom; 541 | 542 | var yR = xyz[1]; // (Yr = 1) 543 | var l = yR > CIE.ε ? 116*Math.cbrt(yR) - 16 : CIE.κ * yR; 544 | 545 | var u = 13 * l * (u1 - uR); 546 | var v = 13 * l * (v1 - vR); 547 | 548 | return [l,u,v]; 549 | }, 550 | 551 | toString: function(luv,alpha) { 552 | return "luv(" 553 | + numstr(luv[0]) + "% " 554 | + numstr(luv[1]) + " " 555 | + numstr(luv[2]) + appendAlpha(alpha) + ")"; 556 | } 557 | }; 558 | 559 | (function() { 560 | var lch = { 561 | coords: [{name:"l",range:[0,100]}, 562 | {name:"c",range:[0,Infinity]}, 563 | {name:"h",range:[0,360],isAngle:true}], 564 | 565 | toString: function(lch,alpha) { 566 | return "lch(" 567 | + numstr(lch[0]) + "% " 568 | + numstr(lch[1]) + " " 569 | + numstr(lch[2]) + appendAlpha(alpha) + ")"; 570 | } 571 | }; 572 | 573 | var defineLCH = function(nickname,base) { 574 | var space = {} 575 | 576 | space.coords = lch.coords; 577 | space.toString = lch.toString; 578 | 579 | space.id = nickname; 580 | space.name = "LCH(" + base.id + ")"; 581 | space.white = base.white; 582 | space.from = {} 583 | space.from[base.id] = toLCH; 584 | space.to = {} 585 | space.to[base.id] = toCartesian; 586 | Convert.spaces[space.id] = space; 587 | } 588 | 589 | defineLCH("lchab",Convert.spaces.lab); 590 | defineLCH("lchok",Convert.spaces.oklab); 591 | defineLCH("lchuv",Convert.spaces.luv); 592 | defineLCH("lchsr",Convert.spaces.srlab2); 593 | })(); 594 | 595 | // set default lch space 596 | Convert.spaces.lch = Convert.spaces.lchsr; 597 | 598 | // Convert Lab / Luv to cylindrical coord [lightness, chroma, hue] 599 | function toLCH(tuple) { 600 | var l = tuple[0], 601 | a = tuple[1], 602 | b = tuple[2]; 603 | var c = Math.sqrt(a*a + b*b); 604 | var h; 605 | 606 | if (c <= 0.0001) { 607 | c = 0; 608 | h = NaN; 609 | } else { 610 | h = Math.atan2(b,a) * 180 / Math.PI; // convert to degrees 611 | } 612 | 613 | return [clamp(l,0,100), c, clamp360(h)]; 614 | } 615 | 616 | // Convert from cylindrical coord [lightness (l), chroma, hue] to cartesian coord . 617 | function toCartesian(lch) { 618 | var l = lch[0], c = lch[1], h = lch[2]; 619 | 620 | if (isNaN(h)) { 621 | h = 0; 622 | } else { 623 | h = h * Math.PI / 180; // convert to radians 624 | } 625 | 626 | var a = c * Math.cos(h); 627 | var b = c * Math.sin(h); 628 | return [clamp(l,0,100), a, b]; 629 | } 630 | 631 | // Color space representation adapted from: 632 | // https://github.com/LeaVerou/color.js/blob/master/src/color.js 633 | Object.keys(Convert.spaces).forEach(function(spaceId) { 634 | var space = Convert.spaces[spaceId]; 635 | console.assert(spaceId === "lch" || spaceId === space.id); 636 | if (!space.fromXYZ && !space.toXYZ) { 637 | // add connection space if a space is missing to/from XYZ() 638 | var connectionSpace; 639 | 640 | if (space.from && space.to) { 641 | var from = new Set(Object.keys(space.from)), 642 | to = new Set(Object.keys(space.to)), 643 | candidates = []; 644 | 645 | from.forEach(function(id) { 646 | if (to.has(id)) { 647 | var sp = Convert.spaces[id]; 648 | if (sp && sp.fromXYZ && sp.toXYZ) { 649 | candidates.push(id); 650 | } 651 | } 652 | }); 653 | 654 | if (candidates.length > 0) { 655 | connectionSpace = Convert.spaces[candidates[0]]; 656 | } 657 | } 658 | 659 | if (connectionSpace) { 660 | // define from/to XYZ functions based on the connection space 661 | Object.assign(space,{ 662 | fromXYZ: function(xyz) { 663 | var newCoords = connectionSpace.fromXYZ(xyz); 664 | return this.from[connectionSpace.id].call(this,newCoords); 665 | }, 666 | toXYZ: function(coords) { 667 | var newCoords = this.to[connectionSpace.id].call(this,coords); 668 | return connectionSpace.toXYZ(newCoords); 669 | } 670 | }); 671 | 672 | // add connection space's to/from functions as well, e.g. 673 | // add lab.from to lch's from property 674 | if (connectionSpace.from) { // e.g. lab.from=rgb 675 | Object.keys(connectionSpace.from).forEach(function(id) { 676 | space.from[id] = function(tuple) { 677 | var newCoords = connectionSpace.from[id].call(connectionSpace,tuple); 678 | return this.from[connectionSpace.id].call(this,newCoords); 679 | } 680 | }); 681 | } 682 | if (connectionSpace.to) { 683 | Object.keys(connectionSpace.to).forEach(function(id) { 684 | space.to[id] = function(tuple) { 685 | var newCoords = this.to[connectionSpace.id].call(this,tuple); 686 | return connectionSpace.to[id].call(connectionSpace,newCoords); 687 | } 688 | }); 689 | } 690 | } else { 691 | throw new ReferenceError("No connection space found for " + space.name + "."); 692 | } 693 | } 694 | Object.assign(space,{ 695 | clip: function(coords) { 696 | return clip.call(this,coords); 697 | } 698 | }); 699 | }); 700 | 701 | // map coords to new space WITHOUT forcing into gamut 702 | Convert.map = function(fromSpace,coords,toSpace) { 703 | if (fromSpace === toSpace) { 704 | // Same space, no change needed 705 | return coords.slice(0); 706 | } 707 | 708 | // Use direct to/from if available; otherwise, go through xyz space. 709 | // Custom function takes care any chromatic adaptation and gamut 710 | // mapping. 711 | if (toSpace.from && toSpace.from[fromSpace.id]) { 712 | return toSpace.from[fromSpace.id].call(toSpace,coords); 713 | } 714 | 715 | if (fromSpace.to && fromSpace.to[toSpace.id]) { 716 | return fromSpace.to[toSpace.id].call(fromSpace,coords); 717 | } 718 | 719 | var xyz = fromSpace.toXYZ(coords); 720 | 721 | return toSpace.fromXYZ(xyz); 722 | }; 723 | 724 | Convert.chromaticAdaptation = function(from,to,xyz) { 725 | var M; 726 | 727 | // computed 728 | if (from === CIE.D65.white && to === CIE.D50.white) { 729 | M = [[ 1.0479297925449966, 0.0229468706016096, -0.0501922662892052], 730 | [ 0.0296278087700558, 0.9904344267538798, -0.0170737990634188], 731 | [-0.0092430406462045, 0.0150551914902981, 0.7518742814281371]]; 732 | } else if (from === CIE.D50.white && to === CIE.D65.white) { 733 | M = [[ 0.9554734214880753, -0.0230984549487646, 0.0632592432005706], 734 | [-0.0283697093338637, 1.0099953980813041, 0.0210414411919173], 735 | [ 0.012314014864482 , -0.020507649298899 , 1.3303659262421237]]; 736 | } else { 737 | throw new TypeError("Only Bradford Chromatic Adaptation with white points D50 and D65 are supported."); 738 | } 739 | return matmul(M,xyz); 740 | }; 741 | 742 | // check each coordinate in are within the bounds 743 | Convert.isInSpace = function(space,coords) { 744 | if (typeof space === "string") { 745 | space = Convert.getSpace(space) 746 | } 747 | 748 | var isInSpace = coords.every(function(v,i) { 749 | var epsilon = .00005; 750 | var min = space.coords[i].range[0]; 751 | var max = space.coords[i].range[1]; 752 | return v >= min - epsilon && v <= max + epsilon; 753 | }); 754 | 755 | if (isInSpace) { 756 | space.clip(coords); 757 | } 758 | return isInSpace; 759 | }; 760 | 761 | Convert.getSpace = function(spaceID) { 762 | if (! Convert.spaces.hasOwnProperty(spaceID)) { 763 | throw new TypeError("unknown color space: " + spaceID); 764 | } 765 | return Convert.spaces[spaceID]; 766 | }; 767 | 768 | // clips components of coords to valid range; padd missing members to zero. 769 | function clip(coords) { 770 | var space = this; 771 | 772 | space.coords.forEach(function(c,i) { 773 | if (i >= coords.length) { 774 | coords[i] = 0; 775 | } else if (c.isAngle) { 776 | coords[i] = clamp360(coords[i]); 777 | } else { 778 | coords[i] = clamp(coords[i],c.range[0],c.range[1]); 779 | } 780 | }); 781 | coords.splice(space.coords.length); 782 | return coords; 783 | } 784 | 785 | // 3-digit precision 786 | function numstr(n) { 787 | if (isNaN(n)) { 788 | return "0"; 789 | } 790 | return (Math.round(n*1000)/1000).toString(); 791 | } 792 | 793 | function appendAlpha(a,join) { 794 | if (isNaN(a)) { 795 | return " / 0"; 796 | } 797 | return a < 1 ? " / " + numstr(a) : ""; 798 | } 799 | 800 | module.exports = Convert; 801 | })(); 802 | --------------------------------------------------------------------------------