diff --git a/packages/preview/alertoni/1.0.0/LICENSE b/packages/preview/alertoni/1.0.0/LICENSE new file mode 100644 index 0000000000..6d8cea430e --- /dev/null +++ b/packages/preview/alertoni/1.0.0/LICENSE @@ -0,0 +1,190 @@ +EUROPEAN UNION PUBLIC LICENCE v. 1.2 +EUPL © the European Union 2007, 2016 + +This European Union Public Licence (the ‘EUPL’) applies to the Work (as defined below) which is provided under the +terms of this Licence. Any use of the Work, other than as authorised under this Licence is prohibited (to the extent such +use is covered by a right of the copyright holder of the Work). +The Work is provided under the terms of this Licence when the Licensor (as defined below) has placed the following +notice immediately following the copyright notice for the Work: + Licensed under the EUPL +or has expressed by any other means his willingness to license under the EUPL. + +1.Definitions +In this Licence, the following terms have the following meaning: +— ‘The Licence’:this Licence. +— ‘The Original Work’:the work or software distributed or communicated by the Licensor under this Licence, available +as Source Code and also as Executable Code as the case may be. +— ‘Derivative Works’:the works or software that could be created by the Licensee, based upon the Original Work or +modifications thereof. This Licence does not define the extent of modification or dependence on the Original Work +required in order to classify a work as a Derivative Work; this extent is determined by copyright law applicable in +the country mentioned in Article 15. +— ‘The Work’:the Original Work or its Derivative Works. +— ‘The Source Code’:the human-readable form of the Work which is the most convenient for people to study and +modify. +— ‘The Executable Code’:any code which has generally been compiled and which is meant to be interpreted by +a computer as a program. +— ‘The Licensor’:the natural or legal person that distributes or communicates the Work under the Licence. +— ‘Contributor(s)’:any natural or legal person who modifies the Work under the Licence, or otherwise contributes to +the creation of a Derivative Work. +— ‘The Licensee’ or ‘You’:any natural or legal person who makes any usage of the Work under the terms of the +Licence. +— ‘Distribution’ or ‘Communication’:any act of selling, giving, lending, renting, distributing, communicating, +transmitting, or otherwise making available, online or offline, copies of the Work or providing access to its essential +functionalities at the disposal of any other natural or legal person. + +2.Scope of the rights granted by the Licence +The Licensor hereby grants You a worldwide, royalty-free, non-exclusive, sublicensable licence to do the following, for +the duration of copyright vested in the Original Work: +— use the Work in any circumstance and for all usage, +— reproduce the Work, +— modify the Work, and make Derivative Works based upon the Work, +— communicate to the public, including the right to make available or display the Work or copies thereof to the public +and perform publicly, as the case may be, the Work, +— distribute the Work or copies thereof, +— lend and rent the Work or copies thereof, +— sublicense rights in the Work or copies thereof. +Those rights can be exercised on any media, supports and formats, whether now known or later invented, as far as the +applicable law permits so. +In the countries where moral rights apply, the Licensor waives his right to exercise his moral right to the extent allowed +by law in order to make effective the licence of the economic rights here above listed. +The Licensor grants to the Licensee royalty-free, non-exclusive usage rights to any patents held by the Licensor, to the +extent necessary to make use of the rights granted on the Work under this Licence. + +3.Communication of the Source Code +The Licensor may provide the Work either in its Source Code form, or as Executable Code. If the Work is provided as +Executable Code, the Licensor provides in addition a machine-readable copy of the Source Code of the Work along with +each copy of the Work that the Licensor distributes or indicates, in a notice following the copyright notice attached to +the Work, a repository where the Source Code is easily and freely accessible for as long as the Licensor continues to +distribute or communicate the Work. + +4.Limitations on copyright +Nothing in this Licence is intended to deprive the Licensee of the benefits from any exception or limitation to the +exclusive rights of the rights owners in the Work, of the exhaustion of those rights or of other applicable limitations +thereto. + +5.Obligations of the Licensee +The grant of the rights mentioned above is subject to some restrictions and obligations imposed on the Licensee. Those +obligations are the following: + +Attribution right: The Licensee shall keep intact all copyright, patent or trademarks notices and all notices that refer to +the Licence and to the disclaimer of warranties. The Licensee must include a copy of such notices and a copy of the +Licence with every copy of the Work he/she distributes or communicates. The Licensee must cause any Derivative Work +to carry prominent notices stating that the Work has been modified and the date of modification. + +Copyleft clause: If the Licensee distributes or communicates copies of the Original Works or Derivative Works, this +Distribution or Communication will be done under the terms of this Licence or of a later version of this Licence unless +the Original Work is expressly distributed only under this version of the Licence — for example by communicating +‘EUPL v. 1.2 only’. The Licensee (becoming Licensor) cannot offer or impose any additional terms or conditions on the +Work or Derivative Work that alter or restrict the terms of the Licence. + +Compatibility clause: If the Licensee Distributes or Communicates Derivative Works or copies thereof based upon both +the Work and another work licensed under a Compatible Licence, this Distribution or Communication can be done +under the terms of this Compatible Licence. For the sake of this clause, ‘Compatible Licence’ refers to the licences listed +in the appendix attached to this Licence. Should the Licensee's obligations under the Compatible Licence conflict with +his/her obligations under this Licence, the obligations of the Compatible Licence shall prevail. + +Provision of Source Code: When distributing or communicating copies of the Work, the Licensee will provide +a machine-readable copy of the Source Code or indicate a repository where this Source will be easily and freely available +for as long as the Licensee continues to distribute or communicate the Work. +Legal Protection: This Licence does not grant permission to use the trade names, trademarks, service marks, or names +of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and +reproducing the content of the copyright notice. + +6.Chain of Authorship +The original Licensor warrants that the copyright in the Original Work granted hereunder is owned by him/her or +licensed to him/her and that he/she has the power and authority to grant the Licence. +Each Contributor warrants that the copyright in the modifications he/she brings to the Work are owned by him/her or +licensed to him/her and that he/she has the power and authority to grant the Licence. +Each time You accept the Licence, the original Licensor and subsequent Contributors grant You a licence to their contributions +to the Work, under the terms of this Licence. + +7.Disclaimer of Warranty +The Work is a work in progress, which is continuously improved by numerous Contributors. It is not a finished work +and may therefore contain defects or ‘bugs’ inherent to this type of development. +For the above reason, the Work is provided under the Licence on an ‘as is’ basis and without warranties of any kind +concerning the Work, including without limitation merchantability, fitness for a particular purpose, absence of defects or +errors, accuracy, non-infringement of intellectual property rights other than copyright as stated in Article 6 of this +Licence. +This disclaimer of warranty is an essential part of the Licence and a condition for the grant of any rights to the Work. + +8.Disclaimer of Liability +Except in the cases of wilful misconduct or damages directly caused to natural persons, the Licensor will in no event be +liable for any direct or indirect, material or moral, damages of any kind, arising out of the Licence or of the use of the +Work, including without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, loss +of data or any commercial damage, even if the Licensor has been advised of the possibility of such damage. However, +the Licensor will be liable under statutory product liability laws as far such laws apply to the Work. + +9.Additional agreements +While distributing the Work, You may choose to conclude an additional agreement, defining obligations or services +consistent with this Licence. However, if accepting obligations, You may act only on your own behalf and on your sole +responsibility, not on behalf of the original Licensor or any other Contributor, and only if You agree to indemnify, +defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against such Contributor by +the fact You have accepted any warranty or additional liability. + +10.Acceptance of the Licence +The provisions of this Licence can be accepted by clicking on an icon ‘I agree’ placed under the bottom of a window +displaying the text of this Licence or by affirming consent in any other similar way, in accordance with the rules of +applicable law. Clicking on that icon indicates your clear and irrevocable acceptance of this Licence and all of its terms +and conditions. +Similarly, you irrevocably accept this Licence and all of its terms and conditions by exercising any rights granted to You +by Article 2 of this Licence, such as the use of the Work, the creation by You of a Derivative Work or the Distribution +or Communication by You of the Work or copies thereof. + +11.Information to the public +In case of any Distribution or Communication of the Work by means of electronic communication by You (for example, +by offering to download the Work from a remote location) the distribution channel or media (for example, a website) +must at least provide to the public the information requested by the applicable law regarding the Licensor, the Licence +and the way it may be accessible, concluded, stored and reproduced by the Licensee. + +12.Termination of the Licence +The Licence and the rights granted hereunder will terminate automatically upon any breach by the Licensee of the terms +of the Licence. +Such a termination will not terminate the licences of any person who has received the Work from the Licensee under +the Licence, provided such persons remain in full compliance with the Licence. + +13.Miscellaneous +Without prejudice of Article 9 above, the Licence represents the complete agreement between the Parties as to the +Work. +If any provision of the Licence is invalid or unenforceable under applicable law, this will not affect the validity or +enforceability of the Licence as a whole. Such provision will be construed or reformed so as necessary to make it valid +and enforceable. +The European Commission may publish other linguistic versions or new versions of this Licence or updated versions of +the Appendix, so far this is required and reasonable, without reducing the scope of the rights granted by the Licence. +New versions of the Licence will be published with a unique version number. +All linguistic versions of this Licence, approved by the European Commission, have identical value. Parties can take +advantage of the linguistic version of their choice. + +14.Jurisdiction +Without prejudice to specific agreement between parties, +— any litigation resulting from the interpretation of this License, arising between the European Union institutions, +bodies, offices or agencies, as a Licensor, and any Licensee, will be subject to the jurisdiction of the Court of Justice +of the European Union, as laid down in article 272 of the Treaty on the Functioning of the European Union, +— any litigation arising between other parties and resulting from the interpretation of this License, will be subject to +the exclusive jurisdiction of the competent court where the Licensor resides or conducts its primary business. + +15.Applicable Law +Without prejudice to specific agreement between parties, +— this Licence shall be governed by the law of the European Union Member State where the Licensor has his seat, +resides or has his registered office, +— this licence shall be governed by Belgian law if the Licensor has no seat, residence or registered office inside +a European Union Member State. + + + Appendix + +‘Compatible Licences’ according to Article 5 EUPL are: +— GNU General Public License (GPL) v. 2, v. 3 +— GNU Affero General Public License (AGPL) v. 3 +— Open Software License (OSL) v. 2.1, v. 3.0 +— Eclipse Public License (EPL) v. 1.0 +— CeCILL v. 2.0, v. 2.1 +— Mozilla Public Licence (MPL) v. 2 +— GNU Lesser General Public Licence (LGPL) v. 2.1, v. 3 +— Creative Commons Attribution-ShareAlike v. 3.0 Unported (CC BY-SA 3.0) for works other than software +— European Union Public Licence (EUPL) v. 1.1, v. 1.2 +— Québec Free and Open-Source Licence — Reciprocity (LiLiQ-R) or Strong Reciprocity (LiLiQ-R+). + +The European Commission may update this Appendix to later versions of the above licences without producing +a new version of the EUPL, as long as they provide the rights granted in Article 2 of this Licence and protect the +covered Source Code from exclusive appropriation. +All other changes or additions to this Appendix require the production of a new EUPL version. diff --git a/packages/preview/alertoni/1.0.0/README.md b/packages/preview/alertoni/1.0.0/README.md new file mode 100644 index 0000000000..c0d6d2a1fb --- /dev/null +++ b/packages/preview/alertoni/1.0.0/README.md @@ -0,0 +1,69 @@ +![The banner of the package, which says "Alertoni" with each syilable split up and put into separate callout boxes](docs/banner.svg) + +# Alertoni + +A Typst package that introduces callouts with three different styles and various types. In addition, the package also supports custom styles, types and icon sets. + + +- Read more on how to use it and other functionality in the [Manual](./docs/manual.pdf). + +## Quick Examples + +```typst +#import "@preview/alertoni:1.0.0" as at +``` + +### All Predefined Types + +```typst +#at.callout(type: "info", []) +#at.callout(type: "warning", []) +#at.callout(type: "important", []) +#at.callout(type: "caution", []) +#at.callout(type: "tip", []) +#at.callout(type: "correct", []) +#at.callout(type: "incorrect", []) +#at.callout(type: "example", []) +``` + +![a collection of all types with the default style `"minimal"`](docs/images/all-types.png) + +### All Predefined Styles + +**Note**: you can add your own style. Refer to the manual. + +```typst +#at.callout( + style: "minimal", [Style `"minimal"`] +) + +#at.callout( + style: "quarto", [Style `"quarto"`] +) + +#at.callout( + style: "compact", [Style `"compact"`] +) -- it is also an inline style. +``` + +![a collection of all callout styles](docs/images/all-styles.png) + +### A Custom Type + +```typst +#at.new-type( + name: "hey", + color: olive, + placeholder: "Hello There!", + icon: emoji.hand.wave +) + +#at.callout(type: "hey", [ + #lorem(20) +]) +``` + + +![a custom callout type called "hey", that adds a olive coloured callout with "Hello There!" as title and a wave emoji as icon](docs/images/new-type.png) + +Types can also be langnuage specific and is explained in the manual. diff --git a/packages/preview/alertoni/1.0.0/docs/banner.svg b/packages/preview/alertoni/1.0.0/docs/banner.svg new file mode 100644 index 0000000000..a758b29e20 --- /dev/null +++ b/packages/preview/alertoni/1.0.0/docs/banner.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/preview/alertoni/1.0.0/docs/banner.typ b/packages/preview/alertoni/1.0.0/docs/banner.typ new file mode 100644 index 0000000000..b1ace3679b --- /dev/null +++ b/packages/preview/alertoni/1.0.0/docs/banner.typ @@ -0,0 +1,98 @@ +#import "@preview/alertoni:1.0.0" as at + +#let radius = 3pt +#let inset = (top: 8pt, rest: 6pt) + +#let callout-style(title, icon, content, paint, height, width) = align( + center, + block( + above: 1.5em, + below: 1.5em, + width: width, + height: height, + stroke: paint + 1pt, + inset: inset, + fill: white, + radius: radius, + { + set align(left) + // title block + + if icon != none or title != none { + place(top + left, dy: -inset.top - 0.5em, dx: -1pt, box( + fill: white, + inset: if icon == none { + (x: 2pt) + } else if title == none { + (x: 0pt) + } else { + (left: 1pt, right: 2pt) + }, + outset: (y: 1pt), + grid( + align: center + horizon, + ..if icon != none and title != none { (column-gutter: 0.2em) }, + columns: if icon == none or title == none { + auto + } else { + (1em, auto) + }, rows: 1em, + ..( + if icon != none { + (text(paint, icon),) + } + + if title != none { + (text(weight: "bold", paint, title),) + } + ) + ), + )) + } + content + }, + ), +) + +#let callout = at.callout.with(style: callout-style) + +#set page(width: 21cm, height: 6.8cm, margin: 5mm) +#set text(21pt) + +#let typst-toml = toml("../typst.toml") + +#block(width: 100%, height: 100%, [ + #place(top, { + callout(pad(1.5em, text(5.5em)[A]), width: 40%) + }) + + #place( + top, + { + callout(type: "tip", pad(1em, text(5.5em)[to]), width: auto) + }, + dx: 13.5em, + dy: 0.8em, + ) + + #place( + top, + { + callout(type: "caution", pad(1em, text(5.5em)[ler]), width: auto) + }, + dx: 6em, + dy: 1.6em, + ) + + #place( + top, + { + callout(type: "important", pad(1em, text(5.5em)[ni]), width: auto) + }, + dx: 20em, + dy: 0.4em, + ) + + #place(right+bottom, text(0.7em)[Version #typst-toml.package.version], dy: -0.3em, dx: 0em) +]) + + diff --git a/packages/preview/alertoni/1.0.0/docs/images/all-styles.png b/packages/preview/alertoni/1.0.0/docs/images/all-styles.png new file mode 100644 index 0000000000..65bbe066be Binary files /dev/null and b/packages/preview/alertoni/1.0.0/docs/images/all-styles.png differ diff --git a/packages/preview/alertoni/1.0.0/docs/images/all-types.png b/packages/preview/alertoni/1.0.0/docs/images/all-types.png new file mode 100644 index 0000000000..c90d0b79f0 Binary files /dev/null and b/packages/preview/alertoni/1.0.0/docs/images/all-types.png differ diff --git a/packages/preview/alertoni/1.0.0/docs/images/burger.png b/packages/preview/alertoni/1.0.0/docs/images/burger.png new file mode 100644 index 0000000000..59c653905b Binary files /dev/null and b/packages/preview/alertoni/1.0.0/docs/images/burger.png differ diff --git a/packages/preview/alertoni/1.0.0/docs/images/little-kitty.jpg b/packages/preview/alertoni/1.0.0/docs/images/little-kitty.jpg new file mode 100644 index 0000000000..c18610b14a Binary files /dev/null and b/packages/preview/alertoni/1.0.0/docs/images/little-kitty.jpg differ diff --git a/packages/preview/alertoni/1.0.0/docs/images/new-type.png b/packages/preview/alertoni/1.0.0/docs/images/new-type.png new file mode 100644 index 0000000000..42e06ae0c1 Binary files /dev/null and b/packages/preview/alertoni/1.0.0/docs/images/new-type.png differ diff --git a/packages/preview/alertoni/1.0.0/docs/manual.pdf b/packages/preview/alertoni/1.0.0/docs/manual.pdf new file mode 100644 index 0000000000..8ff909393e Binary files /dev/null and b/packages/preview/alertoni/1.0.0/docs/manual.pdf differ diff --git a/packages/preview/alertoni/1.0.0/docs/manual.typ b/packages/preview/alertoni/1.0.0/docs/manual.typ new file mode 100644 index 0000000000..9383a668cb --- /dev/null +++ b/packages/preview/alertoni/1.0.0/docs/manual.typ @@ -0,0 +1,746 @@ +#import "@preview/alertoni:1.0.0" +#import "@preview/tableau-icons:0.344.0": ti-icon +#import "@preview/shadowed:0.3.0": shadow +#import "@preview/tidy:0.4.3" + +#let package-name = "Alertoni" + +#let typst-toml = toml("../typst.toml") + +#set smartquote( + quotes: ( + double: (sym.quote.chevron.double.l, sym.quote.chevron.double.r), + single: (sym.quote.chevron.l, sym.quote.chevron.r), + ), +) + +#let my-link(link, body) = { + underline(offset: 0.15em, text(blue, std.link(link, body))) +} + +#show `#callout`.text: my-link(label("-callout()"), `#callout`) +#show `#new-type`.text: my-link(label("-new-type()"), `#new-type`) +#show `#set-icons`.text: my-link(label("-set-icons()"), `#set-icons`) + +#show raw.where(block: true): it => { + show `callout`.text: set text(9.5pt) + show `new-type`.text: set text(9.5pt) + show `set-icons`.text: set text(9.5pt) + + show `callout`.text: link(label("-callout()"), `callout`) + show `new-type`.text: link(label("-new-type()"), `new-type`) + show `set-icons`.text: link(label("-set-icons()"), `set-icons`) + + show `callout`.text: underline(offset: 0.2em, "callout") + show `new-type`.text: underline.with(offset: 0.2em) + show `set-icons`.text: underline.with(offset: 0.2em) + it +} + + +/* -------------------------------------------------------------------------- */ +/* Show/Set Rules */ +/* -------------------------------------------------------------------------- */ + + +#alertoni.new-type( + name: "package", + color: blue, + icon: ti-icon("package"), + placeholder: raw(package-name), +) + +#let package-func(title, icon, content, paint, height, width) = { + box(fill: paint.lighten(80%), outset: (y: 0.15em), inset: (right: 0.25em), radius: 0.2em, grid( + columns: 2, + align: horizon, + gutter: 0.25em, + text(top-edge: "bounds", bottom-edge: "bounds", white, box( + grid( + columns: 2, + gutter: 0.25em, + icon, strong(title), + ), + fill: paint, + outset: (y: 0.15em), + inset: (x: 0.15em), + radius: 0.2em, + )), + content, + )) +} + + +#set page( + paper: "a4", + margin: 2.5cm, + footer: block(width: 100%, stroke: (top: (paint: gray, thickness: 0.5pt, dash: "dashed")), inset: (top: 0.5em), align( + center, + context [#counter(page).at(here()).first() #text(gray, [/]) #counter(page).final().first()], + )), + header: context if here().page() != 1 { + block(width: 100%, stroke: (bottom: (paint: gray, thickness: 0.5pt, dash: "dashed")), inset: (bottom: 0.5em))[ + #alertoni.callout( + type: "package", + text(number-width: "tabular", raw(typst-toml.package.version)), + style: package-func, + ) + #h(1fr) + _Package Documentation_ + ] + }, +) + +#set text(lang: "en", region: "CH", font: ("Atkinson Hyperlegible Next", "Noto Color Emoji"), 11pt) + + + +#show heading.where(level: 1): set text(20pt) +#show heading.where(level: 1): set block(above: 1em, below: 1em) +#show heading.where(level: 1, outlined: true): set heading(numbering: (..n) => ( + text(blue, numbering("I", ..n)) + text(gray, weight: "regular", [ \\]) +)) + +#show heading.where(level: 2): set heading(numbering: (..n) => { + [#text(gray, weight: "regular", numbering("I.", n.at(0)))#text(blue, numbering("1", n.at(1)))] +}) + +#show heading.where(level: 3): set heading(numbering: (..n) => { + [#text(gray, weight: "regular", numbering("I.1.", ..n.pos().slice(0, 2)))#text(blue, numbering("a", ..n + .pos() + .slice(2, 3)))] +}) + + + +#set list(marker: text(blue, sym.bullet)) + +#set enum(numbering: n => box(fill: blue, outset: 2pt, radius: 0.2em, text( + white, + weight: "bold", + top-edge: "bounds", + bottom-edge: "bounds", + number-width: "tabular", + numbering("1.", n), +))) + + + +#show raw: set text(font: "Fantasque Sans Mono", 9.5pt) +#show raw.where(block: false): set text(11pt) + +#let my-style(title, _, body, paint, _, _) = { + text(paint, strong[#title ]) + [#body] +} + +#show raw.where(block: true, lang: "example").or(raw.where(block: true, lang: "vexample")): it => { + show grid: set block(sticky: true) + + let inner-inset = if it.lang == "example" { 6pt } else { 6pt } + let outer-inset = if it.lang == "example" { 3pt } else { 3pt } + let radius = 4pt + let spacing = if it.lang == "example" { 5pt } else { 7pt } + let dir = if it.lang == "example" { ltr } else { ttb } + + let hide-hidden = () + let apply-hidden = () + + for l in it.lines { + if l.text.starts-with("///") { + apply-hidden += ((text: l.text.slice(3).trim()),) + } else if l.text.starts-with("//!") { + hide-hidden += ((text: l.text.slice(3).trim()),) + } else { + hide-hidden += (l,) + apply-hidden += (l,) + } + } + + let arrangement(width: 100%, height: auto) = stack( + dir: dir, + spacing: spacing, + block( + ..if it.lang == "example" { (width: width / 2 - spacing / 2, inset: (left: outer-inset)) }, + height: height, + block( + stroke: rgb("#e2e3e8") + 1pt, + radius: radius, + width: 100%, + height: height, + inset: inner-inset, + { + let lines = it.lines + + raw(hide-hidden.map(x => x.text).join("\n"), lang: "typst", block: true) + }, + ), + ), + block( + ..if it.lang == "example" { (width: width / 2 - spacing / 2) } else { (width: 100%) }, + inset: inner-inset, + height: height, + stroke: (paint: rgb("#e2e3e8"), thickness: 1pt, dash: "dashed"), + radius: radius, + { + set text(font: "Atkinson Hyperlegible Next", 9.5pt) + eval(apply-hidden.map(x => x.text).join("\n"), mode: "markup", scope: ( + at: alertoni, + my-style: my-style, + ti-icon: ti-icon, + )) + }, + ), + ) + + if it.lang == "example" { + layout(size => { + arrangement(height: measure(arrangement(width: size.width)).height) + }) + } else { + block(arrangement(), inset: outer-inset) + } +} + + + +#show divider: set align(center) +#show divider: block(above: 1cm, below: 1cm, text( + blue, + top-edge: "bounds", + bottom-edge: "bounds", +)[`<`$ast.op$`>` #box(line(length: 60%, stroke: blue + 0.75pt), baseline: -0.24em) `<`$ast.op$`>`]) + + + + +/* -------------------------------------------------------------------------- */ +/* Functions */ +/* -------------------------------------------------------------------------- */ + +#let pill(content, fill) = { + box(text(font: "Fantasque Sans Mono", content), inset: (x: 3pt), outset: (y: 3pt), fill: fill, radius: 3pt) +} + +#let tytyp = ( + content: pill([content], rgb("#a6ebe6")), + array: pill([array], rgb("#f9dfff")), + dictionary: pill([dictionary], rgb("#f9dfff")), + arguments: pill([arguments], rgb("#ffdfdf")), + integer: pill([integer], rgb("#ffecbf")), + datetime: pill([datetime], rgb("#b7daec")), + color: pill([color], gradient.linear( + angle: 7deg, + (rgb("#7cd5ff"), 0%), + (rgb("#a6fbca"), 33%), + (rgb("#fff37c"), 66%), + (rgb("#ffa49d"), 100%), + )), + string: pill([string], rgb("#d1ffe2")), + length: pill([length], rgb("#ffecbf")), + function: pill([function], rgb("#d1d4fd")), +) + +#let default-red(value) = { + text(0.8em)[default: #text(red, value)] +} +#let default-normal(cont) = { + text(0.8em)[default: #cont] +} + +#let typst-toml = toml("../typst.toml") + +#let callout-types = ("info", "warning", "important", "caution", "tip", "correct", "incorrect", "example") + +#let code-block = block.with(width: 100%, inset: 0.5em, stroke: gray.lighten(50%), radius: 0.3em) + + +#let argument(content, prefix: none) = { + show terms: it => pad(left: it.indent + it.hanging-indent, stack( + ..it.children.map(item => { + h(-it.hanging-indent) + text(font: "Fantasque Sans Mono", if prefix == none [#strong(item.term)] else { + assert(type(prefix) == str, message: "prefix must be a string") + let label = ("param", prefix, item.term.text) + [#strong(item.term) #metadata(label) #std.label(label.join(":"))] + }) + it.separator + item.description + }), + spacing: 1.2em, + )) + + set text(0.9em) + block( + above: 1.5em, + below: 1.5em, + width: 100%, + height: auto, + stroke: gray + 0.5pt, + inset: (top: 8pt, rest: 6pt), + radius: 3pt, + { + set align(left) + // title block + place(top + left, dy: -8pt - 0.5em, dx: -2pt, box(fill: white, inset: (x: 2pt), outset: (y: 1pt), text( + gray, + "Arguments", + ))) + content + }, + ) +} + + + +/* -------------------------------------------------------------------------- */ +/* Content */ +/* -------------------------------------------------------------------------- */ + + + + +#place( + top + center, + scope: "parent", + float: true, + { + v(1cm) + image("banner.svg") + }, +) +#v(2cm) + +#divider() + +#[ + #set heading(outlined: false) + = About +] +#emph(package-name) is a package that introduces various callouts types with three different styles. In addition the package supports custom callout types, custom styling and switching icon sets. + + + + +#divider() + +#{ + show "": typst-toml.package.name + show "": typst-toml.package.version + ```example + //! #import "@preview/:" as at + + #at.callout( + type: "important", + title: [Kitty!], + [ + #image("./images/little-kitty.jpg") + ] + ) + ``` +} + +#place(right, dy: 0.6em, dx: -0.5em, { + show heading.where(level: 1): set block(above: 2em, below: 1em) + show link: underline.with(offset: 0.15em) + show link: set text(blue) + + text( + 0.8em, + )[Photo by #my-link("https://unsplash.com/@kotecinho?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText")[Kote Puerto] on #my-link("https://unsplash.com/photos/white-and-gray-kitten-on-white-textile-so5nsYDOdxw?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText")[Unsplash]] +}) + +#pagebreak() + +#outline() + +#pagebreak() +/* -------------------------------------------------------------------------- */ +/* Main Content */ +/* -------------------------------------------------------------------------- */ + +#show heading.where(level: 1): set block(above: 2em, below: 1em) + += Installation + +#set footnote(numbering: n => text(red, font: "Fantasque Sans Mono", strong[#n])) + + +#[ + #show ``.text: typst-toml.package.version + #show ``.text: typst-toml.package.name + + + + 1. / Install Tabler.io font: + - Tabler.io Icons (#my-link("https://tabler.io/icons", [Webpage Link]) or #my-link("https://cdn.jsdelivr.net/npm/@tabler/icons-webfont@latest/dist/fonts/", [CDN JsDelivr Page])#footnote[You can build the font yourself, the building scripts are available at #my-link("https://github.com/tabler/tabler-icons", "https://github.com/tabler/tabler-icons"). Thus I believe you should have access to these files as well. *But support the icon designers if you can!*]) + + #alertoni.callout( + type: "important", + width: auto, + )[At default settings, this font *is required*!] + + 2. / Import the package: in three different ways + + - Via Typst Universe\ + + #code-block(```typ + #import "@preview/:" as at + ```) + + - Downloading or cloning the repository #raw(lang: "bash", "\"" + typst-toml.package.repository + "\"") and then including the `exports.typ` file.\ + + #code-block(```typ + #import "./path/to/typst-alertoni/exports.typ" as at + ```) + - Via `@local` namespace\ + + #code-block(```typ + #import "@local/:" as at + ```) +] + + + += Usage + +== Callout Styles + +_Styles_ in the context of #emph(package-name) is how the callout look, so the drawing style. The package comes with three predefined styles and allows for user defined styles. + +=== Predefined Styles + +The three predefined styles are #(`"minimal"`, `"compact"`, `"quarto"`).map(x => x.text).map(raw.with(lang: "typc")).join([, ]). The last style #raw(`"quarto"`.text, lang: "typc") is inspired by (aka. almost identical copy of) Quarto's #my-link("https://quarto.org/docs/authoring/callouts.html")[callout blocks]. + +```example +/// #set raw(lang: "typc") +#at.callout( + style: "minimal", [Style `"minimal"`] +) +``` + +```example +/// #set raw(lang: "typc") +#at.callout( + style: "quarto", [Style `"quarto"`] +) +``` + +```example +/// #set raw(lang: "typc") +#at.callout( + style: "compact", [Style `"compact"`] +) -- it is also an inline style. +``` + + +#pagebreak() + +=== Creating & Using Custom Callout Styles + +To allow for a more individual customization of the style, a custom callout style can be defined. To "assign" a custom style, a function in the shape of + +#code-block(```typc +(title, icon, content, paint, height, width) => {...} +```) + + +is passed onto the #my-link(<-callout.style>, `style`) parameter of the `#callout` function. + +```example +#let my-style(title,_,body,paint,_,_) = { + text(paint, strong[#title ]) + [#body] +} + +#at.callout(style: my-style, [ + about a new style! +]) +``` + +#alertoni.callout( + type: "important", + title: [Global Configuration?], + [ + The function is only applied to the callout function it was passed into. To "globally" set a style, see #my-link(, [Tips & Tricks -- Global Configuration]). + + ], + width: 80%, +) + +== Callout Types + +Callout types define the kind of callouts. As with the styles, the package comes with various predefined types and allows for user defined ones to be added. + +=== Predefined Types + +#raw( + lang: "example", + callout-types + .map(x => { + ( + `#at.callout(type: "`.text + + x + + `",`.text + + " " * (calc.max(..callout-types.map(x => x.len())) - x.len()) + + ` [])`.text + ) + }) + .join("\n"), + block: true, +) + +=== Creating & Using Custom Callout Types + +To add custom callout types, the function #my-link(label("-new-type()"), `#new-type()`) is used. Calling this function places the configuration as a state at the call location, meaning you won't be able to use the type BEFORE the call. I recommend setting the types before the overall content! + +Each callout type has an "ID" associated to a couple of configurations: `color`, `icon` and `placeholder`. The term _placeholder_ is used, because the title of the callout is using a placeholder title when no title is specified! + +Now let's create a callout type #raw(`"pizza"`.text, lang: "typc"): + +#code-block(```typst +#at.new-type( + name: "pizza", + color: red, + icon: [🍕], + placeholder: "Pizza Time!" +) +```) + +#let type-name = "pizza" +#let paint = red +#let icon = [🍕] +#let placeholder = "Pizza Time!" + +#alertoni.new-type( + name: "pizza", + color: red, + icon: [🍕], + placeholder: "Pizza Time!", +) + + +With the type added, you can now create callouts and use #raw(`"pizza"`.text, lang: "typc") as type to use it. + +```example +#at.callout(type: "pizza")[#lorem(10)] +``` + +#alertoni.callout(type: "important", width: auto, [ + `#new-type` will overwrite existing entries. +]) + +== Language Context + +The predefined types and, if configured, user defined types can have language specific titles. These get automatically selected when setting the respective language via #raw(`#set text(lang: "..."))`.text, lang: "typst"). + +#alertoni.callout( + type: "caution", + width: auto, + [If no title is found, `#callout` will throw an error, unless a #box(stroke: gray + 0.5pt, outset: (y: 0.3em), inset: (x: 0.2em), radius: 0.2em, `fallback`) entry exists!], +) + +#code-block({ + show "cal!lout": "cal" + sym.zwj + "lout" + ```typst + #let type-name = "pizza" + #let paint = red + #let icon = [🍕] + #let placeholder = ( + fallback: "Pizza Time?" // required if other languages besides the ones below are used + en: "Pizza Time!", + de: "Pizza Zeit!" + ) + + #at.new-type( + name: type-name, + color: paint, + icon: icon, + placeholder: placeholder + ) + ``` +}) + +#let type-name = "pizza" +#let paint = red +#let icon = [🍕] +#let placeholder = ( + en: "Pizza Time!", + de: "Pizza Zeit!", + fallback: "Pizza Time?", +) + +#alertoni.new-type( + name: type-name, + color: paint, + icon: icon, + placeholder: placeholder, +) + +With the type added, you can now create callouts and use #raw(`"pizza"`.text, lang: "typc") as type to use it. Since the placeholder has translations, the callout function will try to select the respective one. + +#colbreak() + +```example +#set text(lang: "en") +#at.callout(type: "pizza")[#lorem(6)] + +#set text(lang: "de") +#at.callout(type: "pizza", [#lorem(6)]) + +#set text(lang: "es") +#at.callout(type: "pizza", lorem(6)) +``` + + +== Modifying the Icon Set + +Per default #emph(package-name) uses the package #my-link("https://typst.app/universe/package/tableau-icons/")[`tableau-icons`] for drawing the icons in the callout. This is internally done via a lookup table (LUT), where each style is assigned an icon as `content`. This of course can be changed via the `#set-icons` function. + +```example +#let icon-set = ( + "info": [*i*], + "warning": [*!*], + "important": [*!!!*], +) + +#at.set-icons(icon-set) + +#at.callout(type: "info", []) +#at.callout(type: "warning", []) +#at.callout(type: "important", []) +``` + +#alertoni.set-icons(auto) + +#alertoni.callout( + type: "info", + width: auto, + [ + When setting icons, existing entries in the internal dictionary\ are updated and new entries are appended. + ], +) + +#let icon-set = ( + "info": [*i*], + "warning": [*!*], + "important": [*!!!*], +) +#alertoni.set-icons(icon-set) + +The `#set-icons` function also supports reseting the icons back to default by passing #raw("auto", lang: "typc"). This also clears #text(red, [all]) user defined icons. + +```example +#at.callout(type: "info", []) +#at.set-icons(auto) +#at.callout(type: "info", []) +``` + +#pagebreak() + += Tips & Tricks + +== Global Configuration + +To globally change the callout style, default type, you can overload the `#callout` function using #raw(`#at.callout.with(..)`.text, lang: "typst"): + +```example +#let quarto-tip = at.callout.with(style: "quarto", type: "tip") + +#quarto-tip[Hello!] +``` + +#alertoni.callout(type: "caution", width: 80%)[ + If you have a multi file project, place it in a "preamble" file, that gets imported in every subdocument that requires callouts. +] + +#alertoni.callout(type: "important", width: 80%)[ + The reason for this kind of implementation is, that I don't want to use custom type packages like #my-link("https://typst.app/universe/package/elembic/", `elembic`) (for now), as I'm waiting for Typst to officially support custom types. + + + It's not the best solution, but a useable workaround until Typst supports custom types. Once these are added, the callout configuration will be configurable via (hopefully): + + #code-block(```typst + #set at.callout(style: my-style, type: "tip") + ```) +] + + +== Writing Shortcut + +To make writing a bit easier or flow nicer, the `#callout` function has a little trick up its sleeve using positonal arguments. By passing an additional positional argument, the first one will be used for the title and the second one as body. + +#align(center, table( + stroke: 0.5pt, + align: (center, left), + columns: 2, + table.header(strong[$\#$ of `pos()`], strong[Effect]), + [$1$], [`[0]`: Body of callout], + [$2$], [`[0]`: Title of callout\ `[1]`: Body of callout], + [$"otherwise"$], [Error is thrown], +)) + +The argument switchup was done to make it easier to read the code line. When reading callouts, usually title is read first, then body. + +```example +#at.callout[No shorthand version] + +#at.callout[Shorthand][Version!] +``` + +#pagebreak() + +== Function Shortcuts + +Another handy use of #raw(`#at.callout.with(..)`.text, lang: "typst") is to create functions for each callout type. For a #raw(`#info`.text, lang: "typst") callout function, you'd declare + +```example +#let info = at.callout.with(type:"info") + +#info(title: [Lorem Ipsum!])[#lorem(10)] +``` + +Function shortcuts were not implemented in the package, as it might conflict with functions in your document. But to make life a bit easier, below are all the predefined types as functions you can copy into your project! + +#code-block(inset: 1em, raw( + block: true, + lang: "typst", + `#import "@preview/alertoni:1.0.0" as at`.text + + "\n\n" + + callout-types + .map(t => { + str(`#let = at.callout.with(type: "")`.text.replace("", t)) + }) + .join("\n"), +)) + +#pagebreak() + += API Reference + +#alertoni.set-icons(auto) // just so docs are clean of any modifications! +#let docs = tidy.parse-module(read("../src/callouts.typ"), scope: ( + at: alertoni, + tytyp: tytyp, + code-block: code-block, + burger-image: image.with("./images/burger.png"), +)) + +#context outline(target: heading.where(level: 2).after(here()), title: none) +#v(2em) + +#tidy.show-module(docs, style: tidy.styles.default, first-heading-level: 1, show-outline: false) + + += Changelog + + +#show heading.where(level: 2): set heading(numbering: none, outlined: false) +#show heading.where(level: 2): it => { + show regex(`\d\.\d\.\d`.text): set text(blue) + show regex(`\\`.text): set text(gray, weight: "regular") + + it +} + +== 1.0.0 \\ Initial Release + +- Added functions `#callout`, `#new-type`, `#set-icons` with documentation! diff --git a/packages/preview/alertoni/1.0.0/exports.typ b/packages/preview/alertoni/1.0.0/exports.typ new file mode 100644 index 0000000000..f139d6feb5 --- /dev/null +++ b/packages/preview/alertoni/1.0.0/exports.typ @@ -0,0 +1 @@ +#import "src/callouts.typ": callout, new-type, set-icons \ No newline at end of file diff --git a/packages/preview/alertoni/1.0.0/src/callouts.typ b/packages/preview/alertoni/1.0.0/src/callouts.typ new file mode 100755 index 0000000000..f3dd4237f3 --- /dev/null +++ b/packages/preview/alertoni/1.0.0/src/callouts.typ @@ -0,0 +1,452 @@ +#import "predefined.typ": default-callout-types, default-icon-set +#import "@preview/tableau-icons:0.344.0": ti-icon + +#let icon-state = state("alertoni-icon-state", default-icon-set) +#let callout-types = state("callout-types", default-callout-types) + + + +#let radius = 3pt +#let inset = (top: 8pt, rest: 6pt) + +#let callout-styles = ( + "minimal": (title, icon, content, paint, height, width) => align( + center, + block( + above: 1.5em, + below: 1.5em, + width: width, + height: height, + stroke: paint + 0.5pt, + inset: inset, + radius: radius, + { + set align(left) + // title block + + if icon != none or title != none { + place(top + left, dy: -inset.top - 0.5em, dx: -1pt, box( + fill: white, + inset: if icon == none { + (x: 2pt) + } else if title == none { + (x: 0pt) + } else { + (left: 1pt, right: 2pt) + }, + outset: (y: 1pt), + grid( + align: center + horizon, + ..if icon != none and title != none { (column-gutter: 0.2em) }, + columns: if icon == none or title == none { + auto + } else { + (1em, auto) + }, rows: 1em, + ..( + if icon != none { + (text(paint, icon),) + } + + if title != none { + (text(weight: "bold", paint, title),) + } + ) + ), + )) + } + content + }, + ), + ), + // inline version + "compact": (title, icon, content, paint, _, _) => { + let inset = 0.3em + + ( + box( + fill: paint.lighten(85%), + outset: inset, + radius: inset, + baseline: inset / 2, + grid( + rows: 1em, + columns: (1em,) * int(icon != none) + (auto,) * int(title != none), align: horizon, gutter: inset, + ..if icon != none { + (text(paint, icon),) + }, + ..if title != none { + (text(strong(title), rgb("#343a40")),) + } + ), + ) + + h(2 * inset) + + content + ) + }, + // the callout styling from the extended Markdown format "Quarto" (https://quarto.org/docs/authoring/callouts.html) + "quarto": (title, icon, content, paint, height, width) => { + let column-count = if title == none or icon == none { + 1 + } else if title != none and icon != none { + 2 + } + + align( + center, + block( + width: width, + height: height, + stroke: (left: paint + 3pt, rest: paint + 0.5pt), + radius: 3pt, + clip: true, + inset: (left: 1.5pt, right: 0.25pt), + grid( + rows: (1.5em, height), + fill: (x, y) => if y == 0 { paint.lighten(85%) } else { none }, + ..if column-count == 2 {( + columns: (1.5em, 1fr), + align: (center + horizon, left + horizon) + )} else {( + columns: (1fr), + align: (left + horizon), + inset: (left: 0.25em) + )}, + ..if icon != none { + ( + text(paint, icon), + ) + }, + ..if title != none { + ( + text(strong(title), rgb("#343a40")), + ) + }, + grid.cell(colspan: column-count, align: left + top, block( + width: 100%, + content, + inset: 0.5em, + )), + ), + ), + ) + }, +) + + + + + +#let callout-invalid-type = ( + color: gray, + placeholder: (de: "Kein Zugehöriger Titel", en: "No Associated Title"), +) + + +/// +/// #example(`#at.callout(title: [Title], [Content])`, scale-preview: 100%) +/// +/// #example(`#at.callout([Content with automatic Title])`, scale-preview: 100%) +/// +/// +/// -> content +#let callout( + /// #let types = ("info", "warning", "important", "tip", "caution", "correct", "incorrect", "example") + /// + /// Type of the callout. Predefined styles are #types.map(x => raw(`"`.text + x + `"`.text, lang: "typc")).join([, ]). + /// + /// If user defined types have been set via #link(label("-new-type()"),`#new-type`), can also contain the respective type name. + /// + /// #example(``` + /// #at.callout(type: "info", lorem(5)) + /// + /// #at.callout(type: "caution", lorem(5)) + /// + /// #at.callout(type: "tip", lorem(5)) + /// ```, scale-preview: 100%) + /// + /// -> string + type: "info", + + /// Rendering style of the callout. Predefined styles are #raw(lang:"typc", `"minimal"`.text), #raw(lang:"typc", `"compact"`.text) and #raw(lang:"typc", `"minimal"`.text). + /// + /// #example(``` + /// #at.callout(style: "minimal", lorem(5)) + /// #at.callout(style: "quarto", lorem(5)) + /// #at.callout(style: "compact", lorem(5)) + /// ```, scale-preview: 100%) + /// + /// + /// Passing a function in the shape of + /// + /// #{ + /// show raw: set text(1.15em) + /// code-block(```typc + /// (title, icon, content, paint, height, width) => {...} + /// ```) + /// } + /// + /// allows for a user defined style. + /// + /// #example(``` + /// #at.callout(style: + /// (title,_,body,paint,_,_) => { + /// [*#text(paint, title)* #body] + /// }, + /// lorem(5) + /// ) + /// ```, scale-preview: 100%) + /// + /// + /// -> string | function + style: "minimal", + + /// Title of the callout. + /// + /// When set to #raw(`auto`.text,lang:"typc") the title is automatically chosen from the (user- or pre-) assigned placeholder title. + /// + /// When set to #raw(`none`.text,lang:"typc"), hides title. If set to anything else, callout title is overwritten. *This applies but is not limited to the predefined styles.* + /// + /// #example(``` + /// #at.callout(icon: auto, lorem(5)) + /// + /// #at.callout(icon: [i], lorem(5)) + /// + /// + /// #at.callout(icon: none, lorem(5)) + /// ```, scale-preview: 100%) + /// + /// + /// -> auto | none | + title: auto, + + /// Width of the callout, but depends on the style. Style #raw(`"compact"`.text,lang: "typc") for + /// example ignores this parameter. + /// + /// -> auto | relative | fraction + width: 100%, + + /// Height of the callout, but depends on the style. Style #raw(`"compact"`.text,lang: "typc") for + /// example ignores this parameter. + /// + /// -> auto | relative | fraction + height: auto, + + /// The icon of the callout. Per default the icon is automatically selected from + /// the respective type configuration. Passing anything that can render as content, + /// overwrites the "default" icon. + /// + /// When set to #raw(`none`.text,lang:"typc"), does not render any icons. *This applies but is not limited to the predefined styles.* + /// + /// #example(``` + /// #at.callout(icon: auto, lorem(5)) + /// + /// #at.callout(icon: [i], lorem(5)) + /// + /// + /// #at.callout(icon: none, lorem(5)) + /// ```, scale-preview: 100%) + /// + /// -> content | auto + icon: auto, + + /// The color of the callout. Per default the color is automatically selected from + /// the respective type configuration. Passing a color, overwrites the "default" + /// color. + /// + /// #example(``` + /// #at.callout(color: auto, lorem(5)) + /// + /// + /// #at.callout(color: purple, lorem(5)) + /// ```, scale-preview: 100%) + /// + /// -> color | auto + color: auto, + + /// The body of the calloutm, *IF* only one position item is passed. If two + /// position items are passed, the first item is the callout, the second one + /// is the callout body. + /// + /// #example(``` + /// #at.callout[No shorthand version] + /// #at.callout[Shorthand][Version!] + /// ```, scale-preview: 100%) + /// + /// This improves writing callouts slightly, as in doesn't break writing flow as much. + ..content, +) = context { + assert( + (std.type(style) == function) or (std.type(style) == str and style in (callout-styles.keys())), + message: "`style` is neither a function or of a valid string: \"minimal\", \"compact\", \"quarto\".", + ) + assert( + content.pos().len() <= 2, + message: "Only one (for content only) or two (for [0] title and [1] content) positonal arguments are accepted!", + ) + + let types = callout-types.get() + let icon-state = icon-state.get() + + assert( + type in types.keys() and type in icon-state.keys(), + message: "The callout type '" + + type + + "' doesn't exist in either type collection or icon set. Have forgotten to add it via 'alertoni.new-type' or 'alertoni.set-icons'?", + ) + let config = callout-types.get().at(type) + + let color = if color == auto { config.color } else { color } + let icon = if icon == auto { icon-state.at(type) } else { icon } + + let title = if content.pos().len() == 2 { + content.pos().first() + } else if title == auto { + if std.type(config.placeholder) == dictionary { + assert( + text.lang in config.placeholder or "fallback" in config.placeholder, + message: "No callout title for language '" + + text.lang + + "' found. Did you forget to add it or a 'fallback' entry?", + ) + + let key = if text.lang not in config.placeholder { "fallback" } else { text.lang } + + config.placeholder.at(key) // the user has to deal with the correct fallback on their own. + } else { + config.placeholder + } + } else { + title + } + + let content = if content.pos().len() == 2 { + content.pos().last() + } else { + content.pos().first() + } + + if std.type(style) == function { + // calls custom function + return style(title, icon, content, color, height, width) + } else { + // Callout Library predefined styles + return (callout-styles.at(style))(title, icon, content, color, height, width) + } +} + +/// Configures the icons by passing a dictionary, which assigns a content value to the respective callout type. +/// +/// #example(``` +/// #let new-set = ( +/// "info": [*i*], +/// "warning": burger-image(width: 100%) +/// ) +/// #at.set-icons(new-set) +/// #at.callout(type: "info", [Hello]) +/// #at.callout(type: "warning", [World]) +/// +/// #at.set-icons(auto) +/// #at.callout(type: "info", [Hello]) +/// #at.callout(type: "warning", [World]) +/// ```, scale-preview: 100%) +/// +#let set-icons( + /// Passing a dictionary in the format of `( : , ...)`, allows you to add or overwrite the icon assignments for specific callout types. + /// + /// + /// Passing #raw(`auto`.text,lang:"typc"), resets all the default types.\ + /// Passing #raw(`none`.text,lang:"typc"), resets all the default types *and* clears entries of user defined types. + /// + /// -> dictionary | auto | none + new-set, +) = { + icon-state.update(x => { + if new-set == auto { + // reset default, keep user defined + return x + default-icon-set + } else if new-set == none { + // reset and clear + return default-icon-set + } + + return x + new-set // add/overwrite new items + }) +} + + +/// #example(``` +/// #at.new-type( +/// name: "test", +/// color: red, +/// icon: text(0.8em)[#emoji.croissant], +/// placeholder: ( +/// fallback: "Title?", +/// en: "A Title", +/// de: "Ein Titel" +/// ) +/// ) +/// +/// #set text(lang: "en") +/// #at.callout(type: "test", [In English]) +/// +/// #set text(lang: "de") +/// #at.callout(type: "test", [In Deutsch]) +/// +/// #set text(lang: "fr") +/// #at.callout(type: "test", [En français?]) +/// ```, scale-preview: 100%) +/// +/// -> none +#let new-type( + /// Name of the new callout type which is also to be used in the #link(label("-callout()"),`#callout`) function. + /// -> str + name: none, + + /// The color of the callout. Depends on the style on how it is used. + /// + /// -> color + color: none, + + /// The icon to be associated with the callout. Everything not #raw(lang: "typc", `none`.text) + /// will be added to the icon-set via #link(label("-set-icons()"),`#set-icons()`). Passing + /// #raw(lang: "typc", `none`.text) skips this step. + /// + /// -> content | str | none + icon: none, + + /// The fallback/automatic title used when no title is given when calling #link(label("-callout()"),`#callout`). + /// Passing a dictionary with the key-value shape of `( : )` allows for language dependent titles (for the languages in the dictionary). + /// + /// #at.callout(type: "important", width: 80%)[If a dictionary is used, #link(label("-callout()"), [\#callout]) will throw an error, if the respective title cannot be found. + /// + /// This can be circumvented via an #raw("\"fallback\"", lang: "typc") entry! + /// ] + /// + /// + /// -> dictionary | content | str + placeholder: none, +) = { + assert(type(name) == str, message: "template name must be a string") + assert(type(color) == std.color, message: "'color' must be of type 'color'.") + + assert(type(icon) in (content, str, symbol) or icon == none, message: "'icon' must be a type of content.") + assert( + type(placeholder) in (dictionary, content, str), + message: "config.placeholder must be either a string/content or a language dictionary '(en: \"..\", de: \"..\")'.", + ) + + if icon != none { + set-icons(((name, icon),).to-dict()) + } + + let config = ( + color: color, + placeholder: placeholder, + ) + + callout-types.update(old => { + old.insert(name, config) + old + }) +} + diff --git a/packages/preview/alertoni/1.0.0/src/predefined.typ b/packages/preview/alertoni/1.0.0/src/predefined.typ new file mode 100644 index 0000000000..2661631538 --- /dev/null +++ b/packages/preview/alertoni/1.0.0/src/predefined.typ @@ -0,0 +1,55 @@ +#import "@preview/tableau-icons:0.344.0": ti-icon + +#let ti-icon = ti-icon.with(top-edge: "bounds", bottom-edge: "bounds") + +// NOTE: the .with is only used, so additional configuraiton using .map can be done ==> .map(v => v()) IS REQUIRED! +#let default-icon-set = ( + "info": ti-icon.with("info-circle"), + "warning": ti-icon.with("alert-triangle"), + "important": ti-icon.with("exclamation-circle"), + "tip": ti-icon.with("bulb"), + "caution": ti-icon.with("traffic-cone"), + "correct": ti-icon.with("check"), + "incorrect": ti-icon.with("x"), + "example": ti-icon.with("tools"), +).map(v => v(top-edge: "bounds", bottom-edge: "bounds")) + + + + +#let default-callout-types = ( + // quarto based callouts + info: ( + color: rgb("#2780e3"), + placeholder: (de: "Information", en: "Information", fallback: "Information"), + ), + warning: ( + color: rgb("#ff7518"), + placeholder: (de: "Warnung", en: "Warning", fallback: "Warning"), + ), + important: ( + color: rgb("#ff0039"), + placeholder: (de: "Wichtig", en: "Important", fallback: "Important"), + ), + tip: ( + color: rgb("#3fb618"), + placeholder: (de: "Tipp", en: "Tip", fallback: "Tip"), + ), + caution: ( + color: rgb("#f0ad4e"), + placeholder: (de: "Vorsicht", en: "Caution", fallback: "Caution"), + ), + // my callouts + correct: ( + color: green.darken(5%), + placeholder: (de: "Korrekt", en: "Correct", fallback: "Correct"), + ), + incorrect: ( + color: red.darken(5%), + placeholder: (de: "Inkorrekt", en: "Incorrect", fallback: "Incorrect"), + ), + example: ( + color: rgb("#966FD6"), + placeholder: (de: "Beispiel", en: "Example", fallback: "Example"), + ), +) \ No newline at end of file diff --git a/packages/preview/alertoni/1.0.0/typst.toml b/packages/preview/alertoni/1.0.0/typst.toml new file mode 100644 index 0000000000..9ae7affb23 --- /dev/null +++ b/packages/preview/alertoni/1.0.0/typst.toml @@ -0,0 +1,11 @@ +[package] +name = "alertoni" +version = "1.0.0" +entrypoint = "exports.typ" +authors = [ "Joel von Rotz <https://joelvonrotz.ch/>"] +license = "EUPL-1.2" +description = "A package for callouts/alerts/alert boxes with support for custom styles & types." +keywords = ["compact", "callouts", "custom callouts"] +categories = ["components", "layout", "utility"] +exclude = [ "docs", ".gitignore",] +repository = "https://codeberg.org/joelvonrotz/typst-alertoni"