Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ node_modules/
*.properties
gradle.properties

iosApp
iosApp

# Internal testing module (not for public release)
testing/
testing
41 changes: 41 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Changelog

All notable changes to PiscesSpotlight will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.2.0] - 2025-01-XX

### Fixed
- Fixed tooltip position jumping/flickering between tutorial steps
- Eliminated layout recalculation that caused visible position shifts

### Changed
- Tooltip height now defaults to fixed 200dp (previously dynamic/nullable)
- Tooltip content is now scrollable when it exceeds available space
- Title text limited to 2 lines with ellipsis
- Description text limited to 5 lines with ellipsis
- Button now anchored to bottom of tooltip card using weighted spacer

### Added
- Binary compatibility validator plugin for API tracking
- Improved tooltip layout consistency across all steps

## [0.1.0] - 2025-01-XX

### Added
- Initial release of PiscesSpotlight
- Cross-platform support for Android, iOS, and Desktop
- Type-safe spotlight target system
- Smart tooltip positioning with automatic edge detection
- Support for multiple concurrent tutorials
- Reactive state management using Compose primitives
- Customizable tooltip positions (Top, Bottom, Left, Right)
- Flat API structure using CompositionLocal
- String-based target support as alternative to type-safe targets
- Tutorial progression controls (next, complete, reset)
- Platform-specific screen dimension handling

[0.2.0]: https://github.com/xcodebn/piscespotlight/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/xcodebn/piscespotlight/releases/tag/v0.1.0
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Add PiscesSpotlight to your Compose Multiplatform project:

```kotlin
commonMain.dependencies {
implementation("io.github.xcodebn:pisces-spotlight:0.1.0")
implementation("io.github.xcodebn:pisces-spotlight:0.2.0")
}
```

Expand Down
9 changes: 9 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@ plugins {
// in each subproject's classloader
alias(libs.plugins.androidApplication) apply false
alias(libs.plugins.androidLibrary) apply false
alias(libs.plugins.binaryCompatibilityValidator)
alias(libs.plugins.composeMultiplatform) apply false
alias(libs.plugins.composeCompiler) apply false
alias(libs.plugins.kotlinMultiplatform) apply false
}

apiValidation {
// Only validate the spotlight library module
ignoredProjects.addAll(listOf("demo", "testing"))

// Validate public API for all supported platforms
nonPublicMarkers.add("io.piscesbn.xcodebn.piscespotlight.InternalPiscesSpotlightApi")
}
2 changes: 1 addition & 1 deletion demo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The demo showcases a 7-step tutorial covering:
This demo uses the published Maven Central version of PiscesSpotlight:

```kotlin
implementation("io.github.xcodebn:pisces-spotlight:0.1.0")
implementation("io.github.xcodebn:pisces-spotlight:0.2.0")
```

## Key Implementation Highlights
Expand Down
2 changes: 1 addition & 1 deletion demo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ kotlin {
implementation(libs.androidx.activity.compose)
}
commonMain.dependencies {
implementation("io.github.xcodebn:pisces-spotlight:0.1.0")
implementation("io.github.xcodebn:pisces-spotlight:0.2.0")
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material3)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fun PDFSummarizerApp() {
UploadButtonTarget,
"Upload PDF",
"Start by uploading a PDF document you want to summarize",
TooltipPosition.Bottom
TooltipPosition.Top
),
SpotlightStep(
SummarizeButtonTarget,
Expand All @@ -52,19 +52,25 @@ fun PDFSummarizerApp() {
HighlightToolTarget,
"Highlight Tool",
"Use this to highlight important sections in your document",
TooltipPosition.Bottom
TooltipPosition.Top
),
SpotlightStep(
AnnotateToolTarget,
"Annotate Tool",
"Add notes and comments to your PDF",
TooltipPosition.Bottom
TooltipPosition.Top
),
SpotlightStep(
ExportToolTarget,
"Export",
"Export your document with annotations",
TooltipPosition.Top
),
SpotlightStep(
SaveButtonTarget,
"Save",
"Save your work and annotations",
TooltipPosition.Left
TooltipPosition.Top
),
SpotlightStep(
AIAssistantTarget,
Expand Down
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ androidx-core = "1.17.0"
androidx-espresso = "3.7.0"
androidx-lifecycle = "2.9.5"
androidx-testExt = "1.3.0"
binaryCompatibilityValidator = "0.17.0"
composeMultiplatform = "1.9.1"
composeIcons = "1.1.1"
junit = "4.13.2"
Expand All @@ -30,6 +31,7 @@ composeIcons-tablerIcons = { module = "br.com.devsrsouza.compose.icons:tabler-ic
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
androidLibrary = { id = "com.android.library", version.ref = "agp" }
binaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binaryCompatibilityValidator" }
composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "composeMultiplatform" }
composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
Binary file added media/pisces_spotlight.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ dependencyResolutionManagement {
}

include(":demo")
include(":spotlight")
include(":spotlight")
include(":testing")
4 changes: 2 additions & 2 deletions spotlight/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Add to your `libs.versions.toml`:

```toml
[versions]
piscesSpotlight = "0.1.0"
piscesSpotlight = "0.2.0"

[libraries]
piscesSpotlight = { module = "io.github.xcodebn:pisces-spotlight", version.ref = "piscesSpotlight" }
Expand All @@ -55,7 +55,7 @@ kotlin {

```kotlin
commonMain.dependencies {
implementation("io.github.xcodebn:pisces-spotlight:0.1.0")
implementation("io.github.xcodebn:pisces-spotlight:0.2.0")
}
```

Expand Down
129 changes: 129 additions & 0 deletions spotlight/api/android/spotlight.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
public final class io/piscesbn/xcodebn/piscespotlight/spotlight/PiscesSpotlightKt {
public static final fun PiscesSpotlightContainer (Lio/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialState;Ljava/util/List;Lkotlin/jvm/functions/Function1;ZLkotlin/jvm/functions/Function2;Landroidx/compose/runtime/Composer;II)V
public static final fun getLocalPiscesTutorialState ()Landroidx/compose/runtime/ProvidableCompositionLocal;
public static final fun piscesSpotlightTarget (Landroidx/compose/ui/Modifier;Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
public static final fun piscesSpotlightTarget (Landroidx/compose/ui/Modifier;Ljava/lang/String;Landroidx/compose/runtime/Composer;I)Landroidx/compose/ui/Modifier;
public static final fun rememberPiscesTutorialController (Landroidx/compose/runtime/Composer;I)Lio/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialController;
public static final fun rememberPiscesTutorialState (Landroidx/compose/runtime/Composer;I)Lio/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialState;
}

public final class io/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialConfig {
public static final field $stable I
public fun <init> (Ljava/lang/String;Ljava/util/List;ZLkotlin/jvm/functions/Function0;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/util/List;ZLkotlin/jvm/functions/Function0;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()Ljava/util/List;
public final fun component3 ()Z
public final fun component4 ()Lkotlin/jvm/functions/Function0;
public final fun copy (Ljava/lang/String;Ljava/util/List;ZLkotlin/jvm/functions/Function0;)Lio/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialConfig;
public static synthetic fun copy$default (Lio/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialConfig;Ljava/lang/String;Ljava/util/List;ZLkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lio/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialConfig;
public fun equals (Ljava/lang/Object;)Z
public final fun getEnabled ()Z
public final fun getId ()Ljava/lang/String;
public final fun getScreenPredicate ()Lkotlin/jvm/functions/Function0;
public final fun getSteps ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class io/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialController {
public static final field $stable I
public fun <init> (Lio/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialState;)V
public final fun getTargetPositions ()Ljava/util/Map;
public final fun startTutorial (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun stopTutorial ()V
}

public final class io/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialState {
public static final field $stable I
public fun <init> ()V
public final fun clearTutorials ()V
public final fun getActiveTutorial ()Lio/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialConfig;
public final fun getAllTargetPositions ()Ljava/util/Map;
public final fun getCurrentStep ()Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightStep;
public final fun getCurrentStepIndex ()I
public final fun getCurrentTutorialId ()Ljava/lang/String;
public final fun getTargetPosition (Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;)Landroidx/compose/ui/geometry/Rect;
public final fun isCompleting ()Z
public final fun isReady ()Z
public final fun nextStep (Lkotlin/jvm/functions/Function1;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun registerTutorial (Lio/piscesbn/xcodebn/piscespotlight/spotlight/PiscesTutorialConfig;)V
public final fun reset ()V
public final fun resetAll ()V
public final fun shouldShowTutorial ()Z
public final fun startTutorial (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public final fun updateTargetPosition (Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;Landroidx/compose/ui/geometry/Rect;)V
}

public final class io/piscesbn/xcodebn/piscespotlight/spotlight/ScreenDimensions {
public static final field $stable I
public synthetic fun <init> (FFLkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1-D9Ej5fM ()F
public final fun component2-D9Ej5fM ()F
public final fun copy-YgX7TsA (FF)Lio/piscesbn/xcodebn/piscespotlight/spotlight/ScreenDimensions;
public static synthetic fun copy-YgX7TsA$default (Lio/piscesbn/xcodebn/piscespotlight/spotlight/ScreenDimensions;FFILjava/lang/Object;)Lio/piscesbn/xcodebn/piscespotlight/spotlight/ScreenDimensions;
public fun equals (Ljava/lang/Object;)Z
public final fun getHeightDp-D9Ej5fM ()F
public final fun getWidthDp-D9Ej5fM ()F
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class io/piscesbn/xcodebn/piscespotlight/spotlight/ScreenDimensions_androidKt {
public static final fun getScreenDimensions (Landroidx/compose/runtime/Composer;I)Lio/piscesbn/xcodebn/piscespotlight/spotlight/ScreenDimensions;
}

public final class io/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightStep {
public static final field $stable I
public synthetic fun <init> (Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;Ljava/lang/String;Ljava/lang/String;Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;FFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;Ljava/lang/String;Ljava/lang/String;Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;FFLkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;FFILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;FFLkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;
public final fun component2 ()Ljava/lang/String;
public final fun component3 ()Ljava/lang/String;
public final fun component4 ()Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;
public final fun component5-D9Ej5fM ()F
public final fun component6-D9Ej5fM ()F
public final fun copy-Kr38-dQ (Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;Ljava/lang/String;Ljava/lang/String;Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;FF)Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightStep;
public static synthetic fun copy-Kr38-dQ$default (Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightStep;Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;Ljava/lang/String;Ljava/lang/String;Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;FFILjava/lang/Object;)Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightStep;
public fun equals (Ljava/lang/Object;)Z
public final fun getDescription ()Ljava/lang/String;
public final fun getTargetKey ()Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;
public final fun getTitle ()Ljava/lang/String;
public final fun getTooltipHeight-D9Ej5fM ()F
public final fun getTooltipPosition ()Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;
public final fun getTooltipWidth-D9Ej5fM ()F
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public abstract interface class io/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget {
}

public final class io/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTargetKt {
public static final fun toTarget (Ljava/lang/String;)Lio/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget;
}

public final class io/piscesbn/xcodebn/piscespotlight/spotlight/StringTarget : io/piscesbn/xcodebn/piscespotlight/spotlight/SpotlightTarget {
public static final field $stable I
public fun <init> (Ljava/lang/String;)V
public final fun component1 ()Ljava/lang/String;
public final fun copy (Ljava/lang/String;)Lio/piscesbn/xcodebn/piscespotlight/spotlight/StringTarget;
public static synthetic fun copy$default (Lio/piscesbn/xcodebn/piscespotlight/spotlight/StringTarget;Ljava/lang/String;ILjava/lang/Object;)Lio/piscesbn/xcodebn/piscespotlight/spotlight/StringTarget;
public fun equals (Ljava/lang/Object;)Z
public final fun getKey ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}

public final class io/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition : java/lang/Enum {
public static final field Bottom Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;
public static final field Left Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;
public static final field Right Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;
public static final field Top Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;
public static fun getEntries ()Lkotlin/enums/EnumEntries;
public static fun valueOf (Ljava/lang/String;)Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;
public static fun values ()[Lio/piscesbn/xcodebn/piscespotlight/spotlight/TooltipPosition;
}

Loading